# TotalCross Overview

TotalCross is an SDK that speeds up the Graphical User Interface (GUI) for embedded systems and Internet of Things (IoT) devices.

TotalCross is an open source cross-platform SDK developed to bring speed to GUI creation for embedded devices. TotalCross has the development benefits from Java without the need of Java running on the device, as it uses its own bytecode and virtual machine (TC bytecode and TCVM), created specifically for performance enhancement. TotalCross runtime is currently at 5MB to bring mobile grade user experience even for low-end MPUs.

TotalCross is compatible with:

* **Android** 4.0.3 and above (API level 15);
* **iOS** 8.0 and above;
* **Windows** XP and above;
* **Windows** CE;
* **Linux** 32 and 64 bits;
* **Linux ARM**
  * Yocto (ex: [Toradex Boards](https://www.toradex.com/))
  * Angstron
  * Debian (ex: [Raspberry Pi](https://www.raspberrypi.org/))

{% hint style="success" %}
Java was chosen as the development language for TotalCross because it is **one of the largest development communities in the world!** It is on the top three most popular languages, with over **9 million Java developers** worldwide.
{% endhint %}

## No JVM running on the device

TotalCross only uses Java for coding, because the Java Bytecode is converted to TotalCross Bytecode (TC Bytecode) to run on the TotalCross Virtual Machine (TCVM).

![](/files/-MLrDtQpLfDb0fuxuIQY)

## Why do I need TotalCross Bytecode and TotalCross Virtual Machine?

Java is widely used for Desktop, Web and Mobile applications but not so much for embedded applications. Embedded system devices usually need low footprint and high performance. That’s where TotalCross comes in. The TC bytecode and TCVM were built to increase the performance and lower the footprint of an application built with Java by deploying it natively. That means that Java won’t need to run on your embedded device.

The Java virtual machine (JMV) is stack-based while the TotalCross Virtual Machine (TCVM) is register-based. That means that simple functions (like C = A+ B) will potentially need **four instructions in JVM** while only **one instruction is needed in TCVM**.

![](/files/-MLrDtQsnZK2BOfT7m4a)

The TotalCross Virtual Machine (TCVM) is a shared library written from scratch, and has the following features:

* It interprets a proprietary set of opcodes instead of Java Bytecodes.
* It has support for real multi-threading. Note that the TotalCross API does not support concurrency, which must be implemented by yourself.
* TotalCross class (tclass) files store internal information in little endian, the most widely used format of actual microprocessors.
* tclass files are highly optimized to save space. For instance, the constant pool (where strings, constants, and identifiers are stored) is shared among all deployed classes, and each class entry is compressed using zlib.
* It supports headless applications (like daemon applications, without user interface): just implement the interface totalcross.MainClass and this class will be loaded by the TCVM. The appStarting() and appEnding() methods are called and the application exits.
* Supports the method finalize(). This method runs every time the garbage collector (GC) finishes its job. There’s a limitation: no objects can be created inside a finally method, otherwise the method will silently abort itself. Optionally, to improve GC’s performance, you can define in your class a public non-static field named dontFinalize that, if present and set to true, will skip the finalize call. In most cases, finalize() is used to ensure that a class that holds system resources (like file or socket) and should be closed to release these resources is always closed, either because the programmer forgot to do it himself or because the program was halted by an exception. Note that you must define the field dontFinalize and set it to true when the close method is run for the first time. Otherwise the GC will try to finalize an object that was already closed by the programmer, which may cause trouble. Doing so also speeds up the GC.

## Built to be lean

The TotalCross technology started in 2007 to speed up mobile application development. The main target in that time was the [Palm Treo 650](https://en.wikipedia.org/wiki/Treo_650) which had low computing power with:

* 312 MHz Intel PXA270 processor
* 32 MB (Non-Volatile File System built-in, flash shared memory) (23 MB available)

From 2019 TotalCross also supports embedded systems devices, providing great UI/UX.

![](/files/-MLrDtQuzhGcx6AuFjtM)

## Licensing

TotalCross SDK is a Free and Open Source Software (FOSS) under the LGPL v2.1 license. It means no license and runtime fees even for commercial usage, without needing to open the project source code.\
TotalCross revenue model is not based on license and runtime sales. It is based on services (support, integrations and GUI design), complementary technologies and a future marketplace of components.

![](/files/-MLrDtQvikRz7RdafWF7)

### Complying with LGPL v2.1

![](/files/-MLrDtQwl_1B6PyuYQKo)

## Graphics, Palette and Color

TotalCross has a graphics engine written from scratch, and some important performance-tailored decisions were taken.

Regardless of the device’s color depth, the screen and images are stored in a 24 bpp RGB array. All drawings are made into a single off screen, which is then converted on the fly to the device’s screen color depth when the updateScreen() method is called. Note that since 2011, no devices with 8 bpp are released to the market; all of them use at least 16 bpp (65536 colors).

The Graphics class **supports real clipping**, which allowed us to support containers that automatically show scrollbars if components are placed beyond its limits.

**TotalCross also supports screen rotation and collapsible input area**. If the user interface is implemented using only relative coordinates, **it will automatically reposition itself whenever the screen resolution is changed**.

Note that aControl.setRect(getClientRect()) should never be used, otherwise the automatic repositioning will not work. Instead, aControl.setRect(LEFT, TOP, FILL, FILL) should be used to produce the same result without affecting the repositioning. If you really have to use getClientRect(), you must also override the reposition() method to support screen rotation. (see the WorldWatch sample).

Colors are represented by int values in the **0xRRGGBB** format. A null color is represented by the value -1.

## Images

Images in TotalCross supports transparency (also known as alpha-channel). The best way to show images is to generate a PNG image from a vectorized image through Photoshop or any other good editor. Prefer creating a big image (for example, 96x96), then decrease its size at runtime using Image.getSmoothScaledInstance.

## Inheritance and Delegation event models

TotalCross supports both Inheritance (Java 1.0) and Delegation (Java 1.1) event models. The Inheritance model will make your code smaller and faster, but there are some situations that require the usage of the Delegation model.

### onEvent

```java
public class MyProgram extends Container{
    Button pushB;
    ​
    public void initUI(){
        add(pushB = new Button("Push me, please"), CENTER, TOP);
    }
    ​
    public void onEvent(Event event){
        switch (event.type){
            case ControlEvent.PRESSED:
            if (event.target == pushB)
            // handle pushB being pressed
            break;
        }
    }
}
```

### Listener

```java
public class MyProgram extends Container{
    Button pushB;
    ​
    public void initUI(){
        add(pushB = new Button("Push me\nPlease"), CENTER, TOP);
        pushB.addPressListener((e) -> {
            // handle pushB being pressed
        });
    }
}
```

## Security

TotalCross applications are currently impossible to be decompiled, because, as mentioned before, TotalCross uses a proprietary set of opcodes instead of Java Bytecodes. The translation between Java Bytecodes to TotalCross opcodes is done automatically when the application is deployed.

However, this also means that you cannot retrieve your application’s source files from the deployed application, so don’t forget to backup your source files!


# TotalCross Javadoc

You can find our Javadoc [here](https://rs.totalcross.com/doc/).


# TotalCross Changelog

All notable changes to this project will be documented in this file.

## 6.1.0 - July 2020

Welcome to the July 2020 release (version 6.1.0). We hope you enjoy the updates in this version. The key highlights are:

* **Maven plugin new version:** your `pom.xml` file should change;
* **KnowCode Compatibility** - It is now possible to run Android XMLs Layouts on Linux Arm;
* **Virtual Keyboard** - New look and animations;
* **Using external applications** - Through the runtime.exec method;
* **Anonymous user statistics** - There is now an option to contribute by sending anonymous data;
* **Changing the SDL implementation** - Removing the SDL code from within the TotalCross SDK and changing the static to dynamic lin&#x6B;**.**

Join our[ community on the telegram](https://t.me/totalcrosscommunity) to suggest activities and learn about development for embedded systems.

### **Maven plugin new version**

After the latest *Language Support for Java* extension updates, some systems had compatibility issues with Java 11. We launched a new version of the TotalCross maven plugin to solve them, the *1.1.6.* You must change the following line:

```markup
...

<plugin>
  <groupId>com.totalcross</groupId>
  <artifactId>totalcross-maven-plugin</artifactId>
  <!-- This line: -->
  <version>1.1.6</version>
  <configuration>
    <name>${project.name}</name>
    <platforms>
    
...
```

### KnowCode compatibility

In this version, **a name tag was added to ContentHandler** (Pull request [#20](https://github.com/TotalCross/totalcross/pull/20)), making it possible for [KnowCode](https://github.com/totalcross/KnowCodeXML), a tool that uses a neural network, to convert [interface images to XML and TotalCross, allowing it to run on Linux Arm](https://opensource.com/article/20/5/linux-arm-ui) with the **same performance** as an application built directly with the TotalCross SDK

![Home appliance application built with Android XML using KnowCode](/files/-MCSj6IV6Xl9p_XIgvlK)

Find out how to use KnowCode by clicking [here](https://www.youtube.com/watch?v=7o3p14wQPsE).

### Virtual Keyboard

In this milestone some improvements were implemented in the keyboard, which are:

* In Linux Arm the virtual keyboard is enabled by default. To disable it just put `Settings.virtualKeyboard = false` in your `MainWindow`class;&#x20;
* In order to improve performance and make the design cleaner, the `ripple effect` animation on the keyboard buttons was removed;
* In order to obtain more effective responsiveness, the calculations of width and height were changed, leaving it less dependent on absolute values;
* To make the interface richer, `sliding animation` was added to the `popup` and `unpopup` of the virtual keyboard. You can see these changes in detail in pull requests [#40](https://github.com/TotalCross/totalcross/pull/40) and [#65](https://github.com/TotalCross/totalcross/pull/65).

In the images below you can see the visual difference:

#### Before:

![Virtual Keyboard on TCSDK 6.0.3 in Expanding Raspberry Pi Ports sample](/files/-MCnQeIMHjUw3zFs_vHh)

#### After:

![Virtual Keyboard on TCSDK 6.1.0 in Expanding Raspberry Pi Ports sample](/files/-MCwCN3aus7QpuisHEV4)

### External applications

To allow the use of external libraries in the simplest way possible is one of TotalCross goals. There is a [branch in our repository called tcni](https://github.com/TotalCross/totalcross/tree/feature/tcni) which (still a Proof Of Concept) allows the use of these external libraries

{% hint style="warning" %}
TCNI is a foreign function interface programming framework that enables TotalCross/Java code running in a Java virtual machine to call and be called by native applications and libraries written in other languages ​​such as C, C ++ and assembly.
{% endhint %}

But while TCNI is not ready to be launched, we have developed a middle ground t**hat allows the use of external applications** in TotalCross, through the method `runtime.exec()`. This method creates a new process and executes the command you passed in this new process (Pull request [#21](https://github.com/TotalCross/totalcross/pull/21)).&#x20;

For example, create a python script to access a temperature sensor and with the `runtime.exec()` get the return of it, as you can see in this [example](https://www.linkedin.com/posts/brunoamuniz_android-linux-linuxarm-activity-6686008251059847168-u-Sr):

![](/files/-MCT4HaWAwitSFxAG_Al)

To better understand how it works using a sample application click [here](https://learn.totalcross.com/documentation/guides/running-c++-applications-with-totalcross).

### Anonymous user statistics:

When TotalCross decided to become a free and open source tool, the decision was made to no longer require an activation key from the user, which was previously necessary to differentiate free users from customers. As this removal would imply resolving a series of errors and making many changes, the team decided to generate an eternal and unlimited key and use it as a default, provisionally, until we resolve some pending issues and can go back to this point and withdraw it for good.

So in 6.1.0 we went back to that and removed the activation key, including the class `register.java`, as you can see in detail in pull request [#53](https://github.com/TotalCross/totalcross/pull/53)

And to better track which users' preferences when using the TotalCross SDK, we **set up the SDK to ask if the developer wants to contribute anonymous data** and if the answer is positive, we record parameters for Deploy, timezone, launchers, operating system version and version of TotalCross used.

![](/files/-MCSp974VMCHnVPiXFLR)

You can see the details of the implementation in Pull Request [#66](https://github.com/TotalCross/totalcross/pull/66).

### Change in SDL implementation&#x20;

We chose to remove SDL code from the SDK TotalCross in this version t**o improve the build organization** and allow people **to customize the build** of their facilities according to their hardware.

In addition, we changed the SDL link from static to dynamic because:&#x20;

* Allows the distribution to have corrections and be used without having to compile the TC again but the guy needs to install the SDL before TotalCross
* Avoids License compliance problems as [FOSSA](https://app.fossa.com/account/login?next=%2F) warns about the SDL license (GPLv3)

For details, see pull requests [#23](https://github.com/TotalCross/totalcross/pull/23), [#24](https://github.com/TotalCross/totalcross/pull/24), and [#68](https://github.com/TotalCross/totalcross/pull/68).

### Other changes:

* [Reverted scroll flick animation](https://github.com/TotalCross/totalcross/pull/54) back to a previous version to fix a bug that caused the content to be pulled back after a scroll;&#x20;
* Fixed [creation of TotalCross modules(tcz files) using Java headless](https://github.com/TotalCross/totalcross/pull/45);
* Fixed [round border on Container](https://github.com/TotalCross/totalcross/pull/47);&#x20;
* Fixed [Switch Bar not being drawn](https://github.com/TotalCross/totalcross/pull/49);
* Fixed [wrong size returned by FontMetrics.stringWidth(String s)](https://github.com/TotalCross/totalcross/pull/50) on devices that use skia with *.ttf* file type fonts.&#x20;
* Fixed [Torizon/Wayland SDL](https://github.com/TotalCross/totalcross/pull/35) initialization;&#x20;
* Fixed [FadeAnimation](https://github.com/TotalCross/totalcross/pull/33): the animation is now working as intended.

## 6.0.4 - March 2020

### Notes

#### **General**

* Disabled screen shifting on Android and iOS (when clicking on edit the keyboard would appear over edit);
* Added tag name to XML's ContentHandler.

#### **Arm**

* ~~SDL statically linked~~ SDL dynamically linked for Linux x86-64;
* Fix Linux x86 and 64 launcher (x-sharedlib to x-executable).

#### **Android**

* Added Skia for Android so now is supported truetype fonts
* Fixed Android buildType

#### **iOS**

* Added iOS files on public repository;
* Support to Metal on iOS;

#### Linux&#x20;

* Fixed SQLite on Linux Desktop.&#x20;

#### Windows

* There were no changes

#### WinCE

* There were no changes

### Build Information

* Fixed SDK and VM build for all available platform on public repository:
  * WinCE;
  * Windows;
  * Android;
  * Linux;
  * Linux arm x86;
  * Linux arm x64;
* Added build.xml for Ant build (without ProGuard);
* Added documentation about how to build [SDK](https://learn.totalcross.com/documentation/developers-area/how-to-build-totalcross-sdk) and [VM](https://learn.totalcross.com/documentation/developers-area/how-to-build-totalcross-vm-wip).

### Community

* TotalCross is under the **LGPL v2.1**;
* Removed the mirror from GitLab to GitHub: **GitHub** is officially the main repository;
* New [TotalCross-Toradex Image](https://github.com/TotalCross/totalcross-toradex-demo) added on GitHub.

## 5.1.4 to 6.0.3

The remaining changelogs will be added later

## 5.1.3 - 2019-08-28

#### Fixed

* Edit
  * Fixed bug with masks containing two consecutive non-alphanumeric characters - [TotalCross#581](https://gitlab.com/totalcross/TotalCross/issues/581#note_203298404)
  * When used for dates, the calendar now properly opens at the date informed on the edit - TotalCross#550
  * Fixed getCopy() to properly function when the Edit uses the field decimalPlaces - TotalCross#505
* Spinner: fixed Spinner animation repainting over previous frames - TotalCross#568
* OutlinedEdit: fixed NPE when using the cancel button on CalendarBox - TotalCross#547
* PopupMenu: fixed performance issues with Material style caused by onPaint recreating the ninepatch on every refresh. This change also affects the performance of other components that may use PopupMenu, such as ComboBox.

## 5.1.2 - 2019-08-05

#### &#x20;Highlights

* Added support for generating QR codes natively on the device - [#540](https://app.gitbook.com/totalcross/TotalCross/issues/540)

{% hint style="info" %}
**This feature is available on all supported devices, but not on the simulator yet. Refer to the documentation for more information and sample usage**
{% endhint %}

#### &#x20;Fixed

* Camera: Fixed `CAMERA_NATIVE_NOCOPY` - [#554](https://app.gitbook.com/totalcross/TotalCross/issues/554)
* Fixed support to listening events on Android hardware buttons, broken on version 5.1.0 - [#557](https://app.gitbook.com/totalcross/TotalCross/issues/557), [#559](https://app.gitbook.com/totalcross/TotalCross/issues/559), [#560](https://app.gitbook.com/totalcross/TotalCross/issues/560)
* ComboBox: Fixed support for option usePopMenu

## 5.1.1 - 2019-07-16

#### &#x20;Fixed

* Fixed push and local notifications for Android 8+ - [#316](https://app.gitbook.com/totalcross/TotalCross/issues/316)

## 5.1.0 - 2019-07-04

#### Highlights

* YouTube Player: New API for displaying YouTube videos on Android and iOS
* Added support for text prediction when using native keyboard on Android and iOS

#### Fixed

* ListContainer: Fixed Check on ListContainer - TotalCross [#393](https://gitlab.com/totalcross/TotalCross/issues/393)
* InputBox: Removed dummy mask that caused trouble when using setMode - TotalCross [#506](https://gitlab.com/totalcross/TotalCross/issues/506)&#x20;
* Toast: Fixed using '\n' on the String used on Toast.show - TotalCross [#498](https://gitlab.com/totalcross/TotalCross/issues/498)
* Button: Fixed using an image and no text position - TotalCross [#527](https://gitlab.com/totalcross/TotalCross/issues/527)
* Edit: Fixed base line not showing when running on devices with DP smaller than 1, such as most WinCE devices - TotalCross [#389](https://gitlab.com/totalcross/TotalCross/issues/389)
* PopupMenu: Fixed the Android UI style - TotalCross [#369](https://gitlab.com/totalcross/TotalCross/issues/369)

#### Changed

* TabbedContainer: Improved graphical performance and responsiveness

#### Added

* MultiEdit: Added fields to set the text gap - TotalCross#[489](https://gitlab.com/totalcross/TotalCross/issues/489)
* Button: Added constant CENTRALIZE to centralize image and text buttons - TotalCross[#498](https://gitlab.com/totalcross/TotalCross/issues/498)
* Settings: Added field `allowBackup`, which may be used to disable Android's automate cloud backup - TotalCross[#548](https://gitlab.com/totalcross/TotalCross/issues/548)

## 5.0.1 - 2019-05-07

#### &#x20;Added

* Added support for printing on Cielo Lio devices with embedded printer. Refer to the class `totalcross.cielo.sdk.printer.PrinterManager` for usage information.

#### &#x20;Fixed

* Grid: fixed column width sizing - [#480](https://app.gitbook.com/totalcross/TotalCross/issues/480)
* Button: fixed position of contents based on the gap value - [#487](https://app.gitbook.com/totalcross/TotalCross/issues/487)
* CalendarBox: fixed calculation of font size - [#397](https://app.gitbook.com/totalcross/TotalCross/issues/397)
* VirtualKeyboard: fixed Clear button and text input look - [#397](https://app.gitbook.com/totalcross/TotalCross/issues/397)
* Socket: fixed support for open timeout on iOS - [#128](https://app.gitbook.com/totalcross/TotalCross/issues/128)

## &#x20;5.0.0 - 2019-04-15

#### &#x20;Highlights

* TotalCross is now aware of the device's screen pixel density and uses this information to scale UI elements uniformly on different platforms.
* The font size is now expressed in scaleable pixels (sp) and will now scale uniformly on different screens. The font size should now be expressed as a constant value or based on `Settings.deviceFontHeight`, but **never** based on the screen's resolution or target platform.

> ℹ **Existing applications may require adjustments to their font sizes!**

* Improved overrall UI responsiveness and reduced application start time on Android
* Several `Vm.sleep` calls in the vm had their time reduced by 50% or more, some calls were replaced with `Thread.yield()`
* On Android and Java, reduced overhead in the event thread to improve UI responsiveness

&#x20;**Screen density support**

All graphical components can now be scaled to have approximately the same physical height on any screen resolution.

&#x20;**Density by OS**

* Android and iOS: these devices expose a manufacturer-provided screen density value. On TotalCross 5 applications, this value is retrieved by default and used to ensure consistent component sizes across devices
* Java: based on scale, e.g. /scale 0.5 = density 2.0, you can try different densities on the emulator by changing the scale command line argument
* Win32 and WinCE: Most Windows devices do not natively expose screen density information and, thus, are kept at density 1.0. To improve the look and feel on smaller screens, we use a density of 0.75 on screens with width or height less than 320
* Other platforms: nothing changed (= density 1.0)

&#x20;**Font**

The font size is now expressed in scalable pixels (sp), this abstracts away the actual physical dimension (screen pixels) of the font. This way, their actual physical size is calculated based on the screen density. e.g: A font with size of 20sp with different screen resolutions:

* Density 1.0: actual size 20 pixels
* Density 1.5: actual size 30 pixels
* Density 2.0: actual size 40 pixels
* Density 0.75: actual size 15 pixels This change shall render TotalCross apps ready for different screen sizes with minimal implementation effort.

> **Updating for 5.0**
>
> Using Font.getDefaultFontSize is no longer necessary, you may now use constant values and the font size will be adjusted accordingly. Applications that tried to “guess” the appropriate font size based on screen resolution may need adjustments. Applications that used Settings.uiAdjustmentsBasedOnFontHeight should have their graphical components resized more uniformly across different platforms and screen densities.

&#x20;**Density Independent Pixels**

Controls may now have their dimensions expressed in density independent pixels units (dp), which are scaled for the screen based on its pixel density. e.g:

```
// adds Button with height of 20dp
add(new Button("Ok"), RIGHT, BOTTOM, PREFERRED, DP + 20);
```

This is now the preferred way of setting the control’s dimensions.

&#x20;**Improved support for animations**

We now provide a central update event that controls can register for. This event fires periodically and is meant to be used to drive all animations in the framework. In comparison to using timer events for animations, this approach uses less CPU and memory, and behaves better under high CPU usage scenarios.

> **Updating for 5.0**
>
> Several classes were updated to use the new update events and the effect on them should be noticeable without any changes. In special, we would like to highlight the ScrollContainer and the ControlAnimation components. Users are encouraged to replace similar uses of threads, sleeps and timer events with update events.

&#x20;**Smoother scrolling**

The ScrollContainer and the Flick components were updated to provide smoother and more precise scrolling. The changes include the usage of quadratic easing animation and exponential decay. The Flick also factors in the screen’s pixel density and offers the user the option of tuning the flick acceleration. Lastly, Flick also supports consecutive drags to increase the scrolling speed.

> **Updating for 5.0**
>
> Most of the changes made are transparent to the user, but there were some breaking changes on Flick. User may have to remove the usage of fields that are no longer available.

&#x20;**Icon control**

With the new Icon control it’s easier to add beautiful and meaningful icons to your application.

This is now the preferred way of adding icons to your application and should be favored over image files. One major reason to favor icon font sets over images is that they are highly scalable and will look sharp in any resolution while using only a fraction of the system resources an image would use. Material Icons are already bundled with the sdk and the IconType interface may be used to implement more font sets.

&#x20;**Alpha support for Labels and Icons**

It’s now possible to change the opacity of text and icons within Label or Icon controls. This is a key feature to design beautiful applications, as it allows text to remain legible over any background color. Transparent status bar

Currently only supported on Android, but iOS support will be ready soon.

&#x20;**Navigation Drawer**

All the previously listed changes were put in use to futher develop the SideMenuContainer, complying with the Navigation Drawer pattern defined by the Material Design guidelines (<https://material.io/guidelines/patterns/navigation-drawer.html>):

* Action bar height is now 20 dp
* Bar title and menu items using the Roboto Medium font (when available)
* Labels and icons now use the correct font size, weight and opacity
* Keylines and margins are respected both inside and outside the side menu (with a special exception for really small screens)
* Smooth slide-in and out effects, with fade effect during slide removed
* Resting elevation over the content
* Swipe to open support is still in its early stages, but should be functional for most applications
* Adjusts automatically when used with transparent status bar

#### &#x20;Added

* SideMenuContainer.Sub, a collapsible submenu for the navigation drawer
* MaterialWindow, a popup window that slides from the bottom to the top of the screen

#### &#x20;Changed

* Camera: On Android, choosing an image from the Gallery no longer creates a copy of it when not necessary (images from a cloud service still require a local copy) - [#400](https://app.gitbook.com/totalcross/TotalCross/issues/400)
* Java
  * ByteArrayOutputStream: added several missing methods - [#478](https://app.gitbook.com/totalcross/TotalCross/issues/478)
  * System: added method `arraycopy`
  * Charset: method forName now correctly validates the given charset name and may throw `IllegalCharsetNameException`
  * String: added constructor `String(byte[] value, int offset, int count, String encoding)` to allow the creation of strings with a given supported enconding

#### &#x20;Deprecated

* Settings: deprecated field `WINDOWSPHONE`, which will be removed in a future release.

## 4.4.0 - 2019-08-14

#### Fixed

* Android: removed compile flag that caused applications to be unbearably slow in old or low-end devices - TotalCross#561, TotalCross#580
* tccodesign script: fixed script not copying pkg files - TotalCross#572
* Camera: partially reverted changes introduced in version 4.3.3 that caused problems on some devices - TotalCross#574
* Grid: fixed column width sizing - TotalCross#480

## 4.3.9 - 2019-08-05

#### Fixed

* tccodesign script: fixed support for push notification

#### Added

* Added classes [`AsyncTask`](https://learn.totalcross.com/documentation/apis/asynchronous-task) and `ThreadPool` to improve concurrency support, refer to the documentation and the PlayBook for more information and samples

## &#x20;4.3.8 - 2019-05-31&#x20;

#### Highlights&#x20;

* Added support for Android 64 bits - TotalCross[#515](https://gitlab.com/totalcross/TotalCross/issues/515)&#x20;

#### Fixed

* Fixed bug with large CRC or size values overflowing 32 bit integer - TotalCross[#529](https://gitlab.com/totalcross/TotalCross/issues/529)&#x20;

#### Changed

* tccodesign script&#x20;
  * Added --output parameter&#x20;
  * Removed lined that deletes UIStoryLaunch&#x20;
  * Fixed icon problem&#x20;
  * Changed to use a temporary folder during the process

## 4.3.7 - 2019-05-06

#### &#x20;Added

* Added support for native barcode scanning on iOS, without using any external library - [#333](https://app.gitbook.com/totalcross/TotalCross/issues/333)

## &#x20;4.3.6 - 2019-04-13

#### &#x20;Highlights

* Dropped support for Windows Phone 8

#### &#x20;Changed

* HttpStream: Reverts change "Query parameters are now encoded to support the usage of unsafe characters" introduced in 4.3.1 - [#482](https://app.gitbook.com/totalcross/TotalCross/issues/482), [#483](https://app.gitbook.com/totalcross/TotalCross/issues/483)

## &#x20;4.3.5 - 2019-04-01

#### &#x20;Fixed

* Deploy: Fixed bug that would cause a method signature to be included in the constant pool as a class - [#139](https://app.gitbook.com/totalcross/TotalCross/issues/139), [#468](https://app.gitbook.com/totalcross/TotalCross/issues/468)

## &#x20;4.3.4 - 2019-03-20

#### &#x20;Fixed

* Android
  * Reverted back the change reverted on last release and finally fixed the bug that was causing the assets to touble in size - [#358](https://app.gitbook.com/totalcross/TotalCross/issues/358)
* HttpStream: Fixed read operation not retuning EOF when the correct content length is provided on the reply - [#464](https://app.gitbook.com/totalcross/TotalCross/issues/464)

## &#x20;4.3.3 - 2019-03-14

* Changed generation of the TotalCross SDK jar:
  * Annotations `@Deprecated` and `@ReplacedByNativeOnDeploy` are no longer stripped by ProGuard - [#411](https://app.gitbook.com/totalcross/TotalCross/issues/411)
  * Argument names are no longer obfuscated
  * The javadoc jar is now being deployed to our Maven repository - [#391](https://app.gitbook.com/totalcross/TotalCross/issues/391)

#### &#x20;Fixed

* Android
  * Fixed deploy not being able to sign the apk when TOTALCROSS3\_HOME is set with a relative path - [#275](https://app.gitbook.com/totalcross/TotalCross/issues/275)
  * Reverts change on deploy that seems to be causing the assets to double the size in the apk
  * Fixed Camera NATIVE support
* iOS
  * Fixed screen resolution for newer models such as iPhone XS - [#308](https://app.gitbook.com/totalcross/TotalCross/issues/308)

## &#x20;4.3.2 - 2019-01-31

#### &#x20;Fixed

* iOS
  * Usage of "hide keyboard" button on the keyboard - [#347](https://app.gitbook.com/totalcross/TotalCross/issues/347)

## &#x20;4.3.1 - 2019-01-14

#### &#x20;Fixed

* URI: Fixed parse of multibyte characters
* Camera: Fixed regression in release 4.2.2 - [#346](https://app.gitbook.com/totalcross/TotalCross/issues/346)
* ArcChart: Fixed coloring of chart when a single series represents 100% of the data - [#350](https://app.gitbook.com/totalcross/TotalCross/issues/350)

#### &#x20;Changed

* HttpStream: Query parameters are now encoded to support the usage of unsafe characters

#### &#x20;Known issues

* iOS
  * Using the "hide keyboard" button on the keyboard makes it unavailable for the application - [#347](https://app.gitbook.com/totalcross/TotalCross/issues/347)

## &#x20;4.3.0 - 2019-01-04

#### &#x20;Highlights

* Added implementation of PBKDF2WithHmacSHA1
* Removed SMS permissions from Android manifest when using the default deploy options, and added the new option /include\_sms to deploy including them

#### &#x20;Fixed

* iOS
  * Fixed screen dimensions on IPhone XS
* Resign script tccodesign:
  * Fixed issue with provided mobileprovision not being added to the Xcode mobileprovisions folder
  * Temp files are now removed before the script execution
  * Fixed issue with certificate name in the following format: iPhone Distribution|Developer: Provided Name (Team ID)
* ImageList: Fixed bug introduced in version 4.2.0 with the correcion of issue [#192](https://app.gitbook.com/totalcross/TotalCross/issues/192) - [#291](https://app.gitbook.com/totalcross/TotalCross/issues/291)
* DiscoveryAgend: Fixed potential leaks when using service discovery on WinCE
* Grid: Fixed sorting different types of data in Grid - [#297](https://app.gitbook.com/totalcross/TotalCross/issues/297)

#### &#x20;Changed

* Removed SMS permissions from Android manifest when using the default deploy options, and added the new option /include\_sms to deploy including them

#### &#x20;Added

* Added implementation of PBKDF2WithHmacSHA1

#### &#x20;Known issues

* Local notifications do not work on Android 8+. This is caused by a change in the security requirements of the Android native notification API that was not listed in the platform's release changelog. This issue will be fixed on the next release of TotalCross 5, but a fix for version 4 won't be issued to maintain our current compatibility with older Android devices.

## &#x20;4.2.7 - 2018-12-06

#### &#x20;Fixed

* Camera: Added request for external storage permission - [#304](https://app.gitbook.com/totalcross/TotalCross/issues/304)
* JSONFactory
  * Fixed processing of arrays in complex objects and added support for non-static inner classes - [#326](https://app.gitbook.com/totalcross/TotalCross/issues/326)
  * Fixes bug on json parsing caused by usage of a regex expression

## &#x20;4.2.6 - 2018-12-03

#### &#x20;Fixed

* Vm.exec: Added permission REQUEST\_INSTALL\_PACKAGES to allow the application to install an apk on Android 8+
* TreeMap: Fixed import of java.lang.Comparable

#### &#x20;Changes

* Scanner: Added camera permission request on Android (ZXing/Scandit)

## &#x20;4.2.5 - 2018-11-29

#### &#x20;Fixed

* Fixed location permission request

#### &#x20;Changes

* Camera: Removed picture rotation detection on Android - it was source of intermittent bugs on some Samsung and Motorola devices

## &#x20;4.2.4 - 2018-11-26

#### &#x20;Fixed

* Fixed permission requests for File constructor, delete and getSize on Android 6+ - [#317](https://app.gitbook.com/totalcross/TotalCross/issues/317)
* Fixed permission request for Camera on Android 6+
* Fixed Vm.exec on Android: intents were not being able to pass external files to other applications - [#69](https://app.gitbook.com/totalcross/TotalCross/issues/69), [#320](https://app.gitbook.com/totalcross/TotalCross/issues/320), [#232](https://app.gitbook.com/totalcross/TotalCross/issues/232) fixes

#### &#x20;Changes

* GPS permission is no longer requested when the application is launched, instead the permission is automatically requested when required by the application

## &#x20;4.2.3 - 2018-11-07

#### &#x20;Fixed

* Fixed regression with the Android deploy that would produce an apk not acceptable by the Play Store
* Radio
  * Fixed autoSplit when the control width is set to PREFERRED

## &#x20;4.2.2 - 2018-10-30

#### &#x20;Fixed

* Camera
  * Fixed CAMERA\_CUSTOM not taking pictures when the device is held on vertical position, this affected a few models, most notably Samsung tablets - [#233](https://app.gitbook.com/totalcross/TotalCross/issues/233)

#### &#x20;Changes

* Container
  * Method getChildren changed to return an empty array instead of null when the container has no children.

## &#x20;4.2.1 - 2018-10-19

#### &#x20;Fixed

* Notification
  * Fixed notification crashing on Android - [#255](https://app.gitbook.com/totalcross/TotalCross/issues/255)
  * Clicking on a notification will no longer start a new instance of the application if there's already one running on background
* PushButtonGroup
  * Fixed regression on PushButtonGroup that made them unclickable on Win32, affecting all dialogs - [#263](https://app.gitbook.com/totalcross/TotalCross/issues/263)

#### &#x20;Changes

* Added a new virtual keyboard that looks more closely to the Android native keyboard and is now the default for Edit and MultiEdit.
* HttpStream: Added support for http methods PUT, PATCH and DELETE in class HttpStream - [#240](https://app.gitbook.com/totalcross/TotalCross/issues/240)

## &#x20;4.2.0 - 2018-10-01

#### &#x20;Highlights

* Android
  * Android package is now built with SDK 27 (previous releases were built with SDK 22) and the latest NDK r17b (up from NDK r8b!) - The minimum SDK level required to run TotalCross applications remains unchanged (SDK 10)
  * Applied the Android recommended changes to better handle activities and contexts to prevent possible resource
  * TotalCross now asks for the user permission to access phone state and location on startup

🚧 **On Android, features that require user permission during runtime may not be working. Please report if you have any trouble with permissions.**

* iOS
  * iOS package is now built with SDK 12
  * Added permission request to use the camera
* General
  * Improved some Color methods to produce better results by properly weighting the RGB components according to our perception of color brightness
  * Added support for local notifications on JDK, Android and iOS.
  * EscPosPrintStream - New API to handle ESC/POS printer commands
  * Added support for fast IDCT scaling on jpeg images. Combined with the usage of the new utility classes to manage scaling jpeg images, this can greatly reduce the memory footprint of jpeg images and improve graphical performance.

> ℹ **Using this approach to handle images of approximately 800x800 on medium sized devices can reduce memory consumption by up to 80% while doubling the image loading speed!**

#### &#x20;Fixed

* Fixed bug during activation with some JDK versions - a FileNotFoundException could be thrown when trying to recursively create directories for a new file
* Deploy
  * Will now correctly package tcz dependencies that were split over multiple files - [#214](https://app.gitbook.com/totalcross/TotalCross/issues/214)
  * Added protection for unlikely (but possible) NPE
  * Fixed deploy with Java 10, dependencies are now listed in the jar's Manifest
  * Fixed NPE when deploying for Win32 without initializing Launcher.instance - [#165](https://app.gitbook.com/totalcross/TotalCross/issues/165)
  * Fixed rare (but possible) NPE during deploy
  * Fix path for Win32 dll, case sensitive systems expect binaries on lowercased folders - [#274](https://app.gitbook.com/totalcross/TotalCross/issues/274)
* Scanner
  * Fixed barcode scanning on Dolphin/Honeywell devices - value of barcode's check digit was being carried over to the calculation of the check digit on the next reading - [#228](https://app.gitbook.com/totalcross/TotalCross/issues/228)
* ComboBox
  * Fixed vertical alignment of text - [#192](https://app.gitbook.com/totalcross/TotalCross/issues/192)
* ImageControl
  * Removed duplicated field `effect`
  * Fixed detection of press events
* Toast
  * Fixed Toast appearing relative to the `topMost` window, when it should always be relative to the MainWindow
* MultiButton
  * Fixed graphical bug - a transparent ComboBox arrow was being drawn on the background of the MultiButton (!)
* PushButtonGroup
  * Fixed drag event to allow "giving up" on a press event by dragging outside the button bounds after a press
* MultiEdit
  * Fixed text being hidden with Material style
  * Fixed bug that made every even character to disappear when you typed and reappear when you typed the next one
* AccordionContainer
  * Fixed arrows not changing state when switching focus between multiple collapsible panes
* CalculatorBox
  * Fixed enconding error with plus-minus sign - [#206](https://app.gitbook.com/totalcross/TotalCross/issues/206)
* Grid
  * Fixed column width wrong resize when dragging edge to before column start - [#186](https://app.gitbook.com/totalcross/TotalCross/issues/186)
* JSONFactory
  * Fixed recursive creation of complex objects
  * Improved JSON parser to map methods camel cased to underscored fields in the JSON object

#### &#x20;Changes

* Updated version of the Bouncy Castle dependency
* On Java, Settings.appPath is now initialized even if the Launcher isn't executed - [#165](https://app.gitbook.com/totalcross/TotalCross/issues/165)
* Launcher
  * The Launcher (simulator) can no longer be used without an activation key
* Deploy
  * Check paths from pkg file and throw more meaningful error message when a path is invalid
  * Print Deploy exceptions on System.err instead of System.out and using the default stack trace output
* Whiteboard
  * No longer recreates the content image when repositioned - [#187](https://app.gitbook.com/totalcross/TotalCross/issues/187), [#196](https://app.gitbook.com/totalcross/TotalCross/issues/196)
* ListBox
  * Deprecated method `add(Object[] moreItems, int startAt, int size)` as it was redundant and more confusing than helpful
* ComboBox
  * Deprecated method `add(Object[] moreItems, int startAt, int size)` as it was redundant and more confusing than helpful
* Radio
  * Added feature autosplit - [#180](https://app.gitbook.com/totalcross/TotalCross/issues/180)

#### &#x20;Added

* EscPosPrintStream - New API which supports several ESC/POS printer commands - refer to the class documentation and samples for more information
* Notification and NotificatonManager - Allows the creation and presentation of local notifications to the user, currently implemented for Android, iOS and Java.
* ImageLoader - New class to help managing image resources, especially jpeg images. Currently no caching is done by the class.
* Image
  * Added static methods `Image.getJpegScaled` and `Image.getJpegBestFit` to load jpeg files using fast IDCT scale, more about this [here](http://jpegclub.org/djpeg/)
* Java
  * Added classes ByteArrayOutputStream and UncheckedIOException
  * Added classes Charset and UnsupportedCharsetException, added also `String.getBytes(Charset)`
* Added Cp437CharacterConverter, which supports encoding and decoding characters using the CP-437 charset (also known as IBM437, windows-437, among others). Especifically added to be used with EscPosPrintStream to properly support writing text to Leopardo A7.
* Convert
  * Added method `charsetForName(String name)`, which returns one of the registered charsets available
  * Added method `registerCharacterConverter(AbstractCharacterConverter characterConverter)`, which allows users to create and registers their own subclass of AbstractCharacterConverter to support custom encodings
  * Added several aliases to the existing ISO-8859-1 and UTF-8 CharacterConverter classes and changed `setDefaultConverter` to be case insensitive and support any of listed aliases.

> The existing CharacterConverter class and subclasses were changed to extend AbstractCharacterConverter, which extends Charset. The actual support to Java Charset is almost none, the main goal is to allow the usage `String.getBytes(Charset)` with the existing CharacterConverter and let users encode strings with different charsets without changing the charset used by the rest of the application through Convert.setDefaultConverter.

#### &#x20;Deprecated

* ListBox
  * Deprecated method `add(Object[] moreItems, int startAt, int size)` as it was redundant and more confusing than helpful
* ComboBox
  * Deprecated method `add(Object[] moreItems, int startAt, int size)` as it was redundant and more confusing than helpful

#### &#x20;Known issues

* iOS
  * Applications signed for enterprise distribution cannot run on iOS 12 - apparently it fails to validate the certification chain that validates the signed application. It's not clear yet if this was an intended change or a bug, but there's no word from Apple about it yet.
  * Applications signed for distribution through the AppStore cannot be uploaded because of changes on the way image resources are handled starting from iOS 11. We are working on a definite fix for this, in the mean time feel free to contact us to manually package the application for the AppStore.
* Notification
  * Android lacks support for custom images for notifications, only the default TotalCross logo is supported
  * Notification crashing application on Android - [#255](https://app.gitbook.com/totalcross/TotalCross/issues/255)
* PushButtonGroup
  * The fix for the drag event caused PushButtonGroup to be unclickable on Win32, affecting all dialogs - [#263](https://app.gitbook.com/totalcross/TotalCross/issues/263)

## &#x20;4.1.4 - 2018-05-17

#### &#x20;Highlights

* TotalCross is now built with the iOS 11 SDK, as a side effect the minimum iOS version supported by TotalCross is now 8.0 (up from 5.1.1). Applications published on the Apple Store must be updated.

## &#x20;4.1.3 - 2018-04-12

#### &#x20;Fixed

* Fixed Edit's material caption animation when navigating using the keyboard
* Fixed `WrapInputStream.read()` - the value returned is now between the range 0-255, as specified by the `InpuStream.read()` documentation. The class `WrapInputStream` is used by `Stream.asInputStream()`
* Fixed `MaterialEffect` to stop discarding `PEN_UP` events sent to the target Control **after** the effect is removed from the target Control
* Implemented `ConnectionManager.getLocalHost()` for iOS
* On iOS, fixed keyboard being closed when navigating to the next text input control using the "Done" button
* Fixed `SideMenuContainer` - the sidemenu is no longer draggable
* Fixed retrieval of the device's current time on newer Android devices (and possibly other POSIX compliant platforms) - [#147](https://app.gitbook.com/totalcross/TotalCross/issues/147)
* Fixed `BarButton` only firing a pressed event targeting itself when Material UI style is used - [#176](https://app.gitbook.com/totalcross/TotalCross/issues/176)
* Fixed redraw after the device is unlocked on Moto G5 Plus - [#173](https://app.gitbook.com/totalcross/TotalCross/issues/173)
* Fixed javadocs not being included with the SDK

#### &#x20;Changes

* Usage of `Vm.sleep(1)` in the SDK replaced with `Thread.yield()` for clarity sake
* Changes `LineReader` to use `Thread.yield()` between read attempts instead of stoping the Vm for 100 ms
* Spinner's implementation changed to use TimerEvent instead of threads perform the animation
* Edit's material caption animation is faster and will no longer get mixed with the blinking cursor
* &#x20;`WrapInputStream.read(B[], I, I)` no longer rethrows `totalcross.io.IOException` as `java.io.IOException`
* &#x20;`WrapOutputStream.write(B[], I, I)` no longer rethrows `totalcross.io.IOException` as `java.io.IOException`
* &#x20;`WrapInputStream.close()` will now properly close the underlying stream
* &#x20;`WrapOutputStream.close()` will now properly close the underlying stream
* Changed the way we obtain the current device orientation and screen dimensions on Android, the previous implementations were deprecated

## &#x20;4.1.2 - 2018-02-20

#### &#x20;Fixed

* Fixed support for WinCE based scanners that use OpticonH16.dll

#### &#x20;Added

* Added support for native laser scanning for Android based Symbol/Motorola scanners

## &#x20;4.1.1 - 2018-02-06

#### &#x20;Highlights

* Launcher default color depth changed from 16 bpp to 24 bpp

#### &#x20;Fixed

* Fixed `Switch` disappearing on Android - calculation of alpha channel applied to the switch was wrong
* Fixed `Socket` and `HttpStream` to properly handle EOF during read operation
* Fixed screen not being shifted when device is in landscape
* Fixed issue where a focused `Edit` would not receive keypress events
* Fixed bug in `Edit` on Android - backspace events would not be issued when the Edit had text but had not received any typing events

#### &#x20;Added

* Added `Edit.canMoveFocus` to disable focus change
* Added `Stream.write(int)`, convenience method to write a single byte to the stream
* Added `ScrollContainer.setScrollBars` to allow subclasses to add or remove scrollbars after its creation
* On Android, Chrome no longer supports using the scheme prefix to display local files. Added workaround to `Vm.exec` to keep backwards compatibility - [#148](https://app.gitbook.com/totalcross/TotalCross/issues/148)
* Added `Settings.ANDROID_ID`, refer to the Android [documentation](https://developer.android.com/reference/android/provider/Settings.Secure.html#ANDROID_ID) for more details
* Added limited support for running Intents through Vm.exec on Android - [#155](https://app.gitbook.com/totalcross/TotalCross/issues/155)

#### &#x20;Changes

* &#x20;`Whiteboard` now supports usage of `transparentBackground` to ignore the background color and generate images with transparent background - [#153](https://app.gitbook.com/totalcross/TotalCross/issues/153)
* Pressing ENTER in a set of `Edit` inside a `ScrollContainer` will now automatically scroll to the next control
* Improved `Control.setRect` error messages, it will now throw distinct messages for invalid width or height

## &#x20;4.1.0 - 2018-01-15

#### &#x20;Highlights

* [Firebase for iOS](https://gitlab.com/totalcross/TotalCross/wikis/Features/Post-Notification---Firebase)
* [SMS changes](https://gitlab.com/totalcross/TotalCross/wikis/Features/sms-manager)
* Implementation for sending and receiving data SMS also disables changing the state of the receiver when the application is paused and resumed
* \[Fade transition]\(<https://gitlab.com/totalcross/TotalCross/wikis/Features/fade> transition)
* Font support
* Improved FontGenerator to create better looking fonts. Regenerate your fonts to make them look smoother on device.
* Spacing between characters was also improved.
* Fixed support for some unicode characters and handling of the ranges passed to the command line.

#### &#x20;Fixed

* Fixed `ScrollContainer` to properly display the controls if the order is changed
* Fixed MaterialEffect on a `ListBox` that was scrolled up
* Fixed Radio not being correctly painted when checked is set to true within the same event that changed it to false
* Fixed `MaterialEffect` fade out duration - alpha is now computed based on remaining time instead of using a constant decreasing value
* Fixed `ScrollPosition`'s handle not being hidden when released
* Fixed Check and Radio sending PRESSED event when `setChecked` is called, even when `Settings.sendPressEventOnChange` is set to false
* Fixed Launcher to better handle missing or bogus font files when running on desktop
* On Graphics, fixed `NullPointerException` and `ArrayIndexOutOfBoundsException` when repaint is called from a thread
* Fixed `ProgressBar` to retain the z-order when its value is updated [#80](https://app.gitbook.com/totalcross/TotalCross/issues/80)
* Fixed iOS icons by adding method `colorDist (int rgb1, int rgb2)` and `addFillPoint (int x, int y)`
* Fixed `ImageControl` zooming with poor quality, it was scaling the resized image displayed in the control instead of the original image
* Fixed usage of internal scanners on Android devices
* Fixed bug where screen was not being shifted when changing focus between Edits using `PEN_UP` or ENTER
* Fixed barcode reading with Motorola scanners when the digits of both halves of the barcode were the same (such as 10161016 or 10201020) - [#106](https://app.gitbook.com/totalcross/TotalCross/issues/106)
* Fixed `NullPointerException` in `Graphics.drawText` that would occur under some situations when the UI is loaded from a thread
* Fixed Window incorrectly calling `onClickedOutside` when a two-finger movement is performed
* Fixed `MaterialEffect` to not apply effects during a flick

#### &#x20;Added

* Added support to Bematech scanner back to the SDK - [#100](https://app.gitbook.com/totalcross/TotalCross/issues/100)
* Added `Settings.showUIErrors`, which can be set to false to disable UI errors that are shown in desktop only.
* Added `Flick.dontPropagate`, which can be useful if you have two or more intrinsic `ScrollContainers` and dont want to propagate the scroll among them
* Added `ScrollContainer.canShowScrollBar`s, which gives child classes finer control on whether scrollbars should be displayed or not
* Added `ComboBox.getArrowColor` and now you can change the arrow color at runtime
* Added classes `java.awt.Dimension` and its dependencies - `java.awt.geom.Dimension2D`, `java.lang.InternalError`, `java.lang.VirtualMachineError`
* Added method `Long.toString(long i, int radix)` to `java.lang.Long`
* Added method `ConnectionManager.getLocalHostName` to retrieve the host name of the local host - [#41](https://app.gitbook.com/totalcross/TotalCross/issues/41)

#### &#x20;Changes

* The tcvm.dll no longer requires elevated privileges to be run on Windows desktop
* Changes `Spinner` to have transparent background by default
* Changes `Spinner` to not mess with the colors when created using an `Image`
* On iOS, the application now receives an ENTER key event when the keyboard is closed
* A `RuntimeException` is no longer raised in JavaSE when you add a control to an `AccordionContainer`, and its height reaches zero during animation
* Changed `ImageControl` to paint material effects only if there is an image and `setPressedEventsEnabled` was called
* Now `Edit.autoSelect` puts cursor at end of line instead of begining, matching the behaviour of `MultiEdit`
* Now if you press ENTER in a set of Edits that are inside a `ScrollContainer`, it scrolls automatically to the next control.
* Increased cursor thickness on `Edit` for devices with high resolution
* Changed `Time(char[] sqlTime)` to also parse the milliseconds value (`SQLite.getTime()` now includes milliseconds)

#### &#x20;Deprecated

The following fields and methods were deprecated and should no longer be used

* `File`
* `readAndClose`
* `eadAndDelete`
* `writeAndClose`
* `read()`
* UIControls
* `spinnerFore`
* `spinnerBack`

## &#x20;4.0.2 - 2017-09-01

#### &#x20;Fixed

* Methods annotated with `@ReplacedByNativeOnDeploy` and array arguments were not being replaced by their native counterpart on deploy
* Fixed deploy to iOS in Linux without X11 display
* Android binaries are now compiled in release mode, because the Play Store no longer allows debug binaries
* TotalCross should no longer require elevated user access to run on Windows desktop
* Fixed pressed event not being fired when the re-selecting the same item on a `ComboBox`
* Fixed crash on WinCE, invalid function references would make the application crash on startup on some devices

#### &#x20;Changes

* Applied annotation `@ReplacedByNativeOnDeploy` on classes of package `totalcross.crypto`, stack trace line numbers should now be the same either on Java or device

## &#x20;4.0.1 - 2017-08-04

#### &#x20;Fixed

* Fixed crash on `File.listFiles` when crawling very big paths
* Fixed support for WinCE devices without the aygshell library, like the Compex PM200
* Fixed `IOException` hierarchy
* Fixed algorithm for `ImageControl.scaleToFit`
* Fixed pressed event not being fired when using a popup with `ComboBox`

#### &#x20;Changes

* Added `CLOSED` state to `File`, which allows it to be properly used in a try-with-resources
* Updated dependency dd-plist.jar to version 1.19

## &#x20;4.0.0 - 2017-07-31

#### &#x20;Highlights

* Familiar with the Material design User Experience? Well, you can now give it to your user!
* &#x20;`@ReplacedByNativeOnDeploy` annotation to denote every method that runs with a native implementation on device
  * The Java implementation is replaced by a native call during the deploy
* &#x20;`java.util.function.*` functional interfaces of Java 8 to provide a deeper dive into functional programming
  * The project needs to be compiled with Java 8 to works, even if it has been downtargeted by RetroLambda
  * &#x20;**NOTE**: no default methods nor static methods yet
* Wish to add your dependencies dynamically? Take a look at [`tc-compiler-help`](https://github.com/TotalCross/tc-compiler-help)
  * The file `all.pkg` is dynamically updated with your dependencies and restored to it's original state
  * See build examples:
    1. Build to multiple platforms [here](https://github.com/TotalCross/IFoodUI/blob/c0e96ade3d24539fb2e96cae2637989c6aea5418/src/main/java/tc/samples/like/ifood/IFoodCompile.java#L12)
    2. Must compile with dependenceis `magical-utils`, `tc-utilities` and `tc-components` [here](https://github.com/TotalCross/totalcross-big-file/blob/master/src/main/java/com/totalcross/sample/bigfile/BigFileCompile.java#L11)

#### &#x20;Fixed

* Prevents null pointer when resizing `ScrollContainer`
* Fixed deploy issue with `java.lang.System` while running with Java 8
* Fixed deploy issue with `java.lang.Character` while running in a headless environment

#### &#x20;Changes

* &#x20;`totalcross.io.Connection` implements `AutoCloseable`, so you may use `try-with-resources` with any `totalcross.io.Stream`, like `HttpStream` or `File`
  * It also warns *Resource leak* when the compiler detects that you are not releasing a opened resource

## &#x20;3.44.3483 - 2017-07-17

#### &#x20;Highlights

* Launcher no longer requires an activation key to run, instead it shows a dismissible popup to input the activation key to be stored on the user's AppData system equivalent directory.
* The stored activation key is used by default for both Launcher and Deploy if the activation key is not provided as a command line argument.

#### &#x20;Fixed

* &#x20;`AccordionContainer.collapseAll` not using `showAnimation` when set to false.
* AccordionContainer expand/collapse not resizing the parent window.
* Fixed not being able to set focus to a Window under the current top one.
* ImageControl not using the alphaMask that may have been assigned to the Image.
* &#x20;`Graphics.getAnglePoint` implementation fixed by using the same algorithm of `Graphics.drawPie`.

#### &#x20;Added

* Added missing qsort methods to Vector to allow sorting in ascending or descending order.

## &#x20;3.43.3452 - 2017-06-29

#### &#x20;Highlights

* Now you can get Firebase identity token to send a unicast message to a single Android device
  * Check the [wiki page](https://gitlab.com/totalcross/TotalCross/wikis/features/firebase-token) for more details;
  * Also check the [GitHub example](https://github.com/TotalCross/totalcross-firebase-token/);
  * Any news, we will keep updating the post and the source

#### &#x20;Fixed

* Deploy with absolute path in Unix system, it isn't anymore mistakenly recognized as a slash argument
* Fixed `ScrollBar.recomputeParams` to ensure the values calculated are within a valid range.
* Fixed TotalCross.apk deploy, which was not including Litebase libraries.
* This affected only applications that used Litebase without packaging TotalCross (option `/p`) on Android.

#### &#x20;Added

* Added missing constructor `Throwable(String, Throwable, boolean, boolean)`
* Added missing constructor `Exception(String, Throwable, boolean, boolean)`
* Added missing constructor `RuntimeException(String, Throwable, boolean, boolean)`
* Added method `Image.resizeJpeg(String inputPath, String outputPath, int maxPixelSize)` to resize images on the file system with a smaller memory footprint.
* On iOS, this method has a native implementation that does not require loading the image on memory, greatly improving performance and memory consumption.
* On every other platform this method will still load the image on memory to perform the resize, but it should still be preferred over other resize methods as we intend to also add native implementation for other platforms in the future.
* Added `Toast.show(final String message, final int delay, final Window parentWindow)`, where you can pass the window where the tooltip will be shown.
* Added `Font.percentBy` which returns a font resized based on the given percentage.

#### &#x20;Changes

* &#x20;`SmsManager.sendTextMessage` asks the SMS composer application to automatically exit after the message is sent, switching back to the TotalCross application
* Set the `MessageBox` default colors in the constructor instead of `onPopup`
* &#x20;`MessageBox` colors will no longer change if the `UIColors` constants are changed after the object is created
* &#x20;`ImageControl` resizes and pans the background image with the foreground image.
* &#x20;`Vm.exec` on Android should now properly execute any video type supported by the viewer, using the MIME type associated with the file extension.
* Unsupported or wrong file extensions may not work, so make sure the file is ok if this method fails to play it.

#### &#x20;Deprecated

* Those classes are no longer used:
* `totalcross.phone.PushNotification`
* `totalcross.ui.event.PushNotificationEvent`

## &#x20;3.42.3362 - 2017-05-25

#### &#x20;Highlights

* New class `SmsManager` to handle sms messages, only on Android for now.
* New component `SideMenuContainer`, a template to make creating applications using a navbar and a sidemenu. This is an incubating feature, therefore backwards compatibility is not guaranteed for future releases.

#### &#x20;Fixed

* Fixed saving photo on portrait [#47](https://app.gitbook.com/totalcross/TotalCross/issues/47)
* Fixed `AccordionContainer` when `showAnimation` is `false`
* Fixed support for Samsung's default keyboard on Android which has a bug related to single character event handling and text prediction [#35](https://app.gitbook.com/totalcross/TotalCross/issues/35)

#### &#x20;Added

* Added support for Compex scanners
* Added `java.sql` exceptions that were being replaced by their equivalents on `totalcross.sql` [#40](https://app.gitbook.com/totalcross/TotalCross/issues/40)
* Added `SmsManager` to send and listen to incoming sms messages, only supported on Android now [#25](https://app.gitbook.com/totalcross/TotalCross/issues/25)
* Added property `Bar.drawBorders` to remove the component's borders
* Added constructor for `TopMenu` to allow using other borders type besides the default `ROUND_BORDER`

#### &#x20;Changes

* Fixed `Edit.clipboardMenu` so that it uses the same font from its parent's Window
* Increased wait time for bluetooth read and write operations on Android [#18](https://app.gitbook.com/totalcross/TotalCross/issues/18)
* Additional check when drawing `TopMenu` to avoid NPE when there are no items to show
* Deprecated method `Image.setTransparentColor` - use images with alpha channel instead

## &#x20;3.41.3331 - 2017-05-10

#### &#x20;Fixed

* Fixed deploy for Android, which was broken on the last release
  * There were some issues with the CI on the last release that could make the deployed application fail to start on Android, but this was fixed and new tests added to the CI to prevent this problem from happening again

## &#x20;3.41.3327 - 2017-05-09

#### &#x20;Highlights

With this new release, TotalCross now supports [Dagger](https://google.github.io/dagger/). A lightweight DI (dependency injection) framework, maintained by Google and with focus on high performance, low startup and better maintainability, which makes it perfect for mobile applications!

Instructions for usage are available on the [wiki](https://gitlab.com/totalcross/TotalCross/wikis/dagger)

#### &#x20;Added

* Added `Vector.ensureCapacity(int)` method
* Added `AccordionContainer.expand(boolean)` and `AccordionContainer.collapse(boolean)`
* Whether one wish to show an animation, just pass `true` as the argument
* Added initial support to some classes and interfaces to provides better Java compliance:
* `java.io.FilterOutputStream`
* `java.io.PrintStream`
* `java.lang.Appendable`
* `java.lang.AssertionError`
* `java.lang.CharSequence`
* &#x20;`java.lang.System`: only the attributes `out` and `err`; both `out` and `err` prints to the `DebugConsole`
* Deploy time support to referencing `java.lang.ref.Reference` and `java.lang.ref.WeakReference`; no semantics **yet**
* Deploy time support to referencing `java.util.concurrent.ConcurrentLinkedQueue`; no semantics **yet**
* `java.inject.Provider`
* &#x20;`java.lang.Class.desiredAssertionStatus()` method, returning `false`
* &#x20;`java.lang.Error(String, Throwable)` constructor
* &#x20;`java.lang.String.contains(CharSequence)` method
* &#x20;`java.lang.String.replaceFirst(String, String)` method
* &#x20;`java.lang.String.subsequence(int, int)` method
* &#x20;`java.lang.StringBuffer.append(CharSequence)` and `java.lang.StringBuffer.append(CharSequence, int, int)` methods
* &#x20;`totalcross.ui.font.Font.toString()` method returns the font name and some other properties
* like `TCFont$N12`
* Added `ImageControl.setImage(Image, boolean)`, where one may tells that it is desired (or not) to reset positions
* &#x20;`OpticonH16.dll` DLL to run proper scanner on WinCE devices

#### &#x20;Changed

* Project files/folder structure ressembles a Maven/Gradle project
* &#x20;`AccordionContainer.expand()` and `AccordionContainer.collapse()` calls `AccordionContainer.expand/collapse(true)`
* If the deploy process does not end happily, it will throw an exception and return code will be non-zero
* &#x20;`ImageControl.setImage(Image)` calls `ImageControl.setImage(Image, boolean)` requesting to reset positions
* Default background color components changed to white
* The Win32 deploy now also copies TotalCross files (dll and tcz) to the application folder

#### &#x20;Fixed

* &#x20;`ComboBox.clear()` now may default to `clearValueInt` when `clearValueStr` is set but not available on the options
* Fixed possible stack overflor on `Throwable` constructors calls
* Fixed `Throwable.toString()` result to match the format used by the JDK
* Pressing enter on iOS devices fires a `SpecialEvent.ENTER` key

## &#x20;3.40.3256 - 2017-04-25

#### &#x20;Added

* Added support to Java 8 Lambda through the usage of [Retrolambda](https://github.com/orfjackal/retrolambda)!
  * &#x20;[Documentation](https://gitlab.com/totalcross/TotalCross/wikis/retrolambda) on how to use it and [sample](https://github.com/TotalCross/HelloTC) are available.
* Added support to refer to a non-TotalCross-recognized HTTP method and forces to send the data
* Added class `totalcross.TotalCrossApplication` which can be used as a main entry point for the application. Check example at [GitHub](https://github.com/TotalCross/HelloTC)
* Added `FONTSIZE` on relative positioning constants
* Added `AccordionContainer.collapseNoAnim`

#### &#x20;Changed

* &#x20;`totacross.sql.ResultSet` and `totalcross.sql.Statement` interfaces extends `Autocloseable`
* &#x20;`LineReader` now uses the current `CharacterConverter`
* Increased height of `ControlBox` to add a few more distance between the message, the control and the buttons
* &#x20;`TopMenu.setRect` visibility changed to protected
* Now if you set `minH` to a negative value, the value will be computed as `-minH * fmH` (font height); this is useful when the font changes dynamically

#### &#x20;Fixed

* SQLite handling correctly UTF8 (if asked to)
* Added `Sound.fromText` (Android only)
  * Check the snippet [$1657156](https://app.gitbook.com/totalcross/TotalCross/snippets/1657156)
* &#x20;`Socket` open timeout in Java working properly
* Fixed `LineReader` reading of a single non-`\n`-terminanted string
* Fixed `Settings.showMousePosition` not taking into account the scale
* Fixed `TopMenu` when the `widthInPixels` is computed dynamically and in a rotation the old value is used instead
* Fixed item's height when a single control is used
* Fixed issue when you set `ScrollContainer.uiAdjustmentsBasedOnFontHeightIsSupported` to false and then the ScrollContainer reseta it to true
* Fixed some issues with Honeywell and Dolphin scanner

## &#x20;3.30.3206 - 2017-03-16

#### &#x20;Added

* Support for IPV6 on iOS

#### &#x20;Changed

* Refactored basic HTTP authentication so that `Proxy Authentication` and `Authentication` uses the same logic int `HttpStream`
* Treating gracefully cancelled photo
* TotalCross VM is now built with Android API level 23

#### &#x20;Fixed

* Fixed basic authentication in `HttpStream`
* Do not deploy placeholder icon, but icon informed icon (Android)
* Workaround to get mac address in Android 6+
* Fixed possible invalid access when freeing a OpenGL texture
* Fixed issue with scanners:
  * Honeywell (Android)
  * Dolphin (WinCE)
* Fixed opening Gallery photo

## &#x20;3.30.3098 - 2017-02-14

#### &#x20;Added

* Implemented base 64 decode stream
  * Check example at [GitHub](https://github.com/totalcross/totalcross-big-file)
    * [Use it like a stream](https://github.com/TotalCross/totalcross-big-file/blob/master/src/main/java/com/tc/sample/bigfile/ui/Utils.java#L15)
* Using [Firebase](https://firebase.google.com/) for push messages in Android
  * Download *google-services.json* and include within your project and it will automagically work

#### &#x20;Deprecated

* GCM is [deprecated by Google itself](https://developers.google.com/cloud-messaging/)
* There is no longer use for `totalcross.sys.Settings.pushTokenAndroid`

#### &#x20;Known issue

* There is no reliable way *yet* to treat Firebase notifications in the app

## &#x20;3.30.3071 - 2017-01-23

#### &#x20;Added

* Implemented `Class.getCanonicalName()`
* Added `java.lang.Autocloseable` interface
* Added `Window.isSipShown()` to check if the keyboard is currently showing
* Added `java.io.InputStream`
* Added `totalcross.io.Stream.asInputStream()`, which returns a `java.io.InputStream` that wraps the original `totalcross.io.Stream`
* Added `java.io.Reader`
* Added `java.io.InputStreamReader`
* Added `java.io.StringReader`
* Added `java.io.Closeable` interface
* Added `java.io.Flushable` interface
* Added `java.io.Writer`
* Added `java.io.StringWriter`
* Added `StringBuffer.append(String, int, int)`
* &#x20;[try-with-resources](https://docs.oracle.com/javase/tutorial/essential/exceptions/tryResourceClose.html) statement supported
* Added a SAX-like compiler for JSON, based on [JSON-Simple](https://github.com/fangyidong/json-simple) and its [Cliftonlabs fork](https://github.com/cliftonlabs/json-simple)
* Added instance method `Control.showTip`

#### &#x20;Fixed

* Avoiding overflow operations within `Long.compareTo(Long)`
* End of stream treated properly in zlib, returns `-1` instead of throwing an exception
* Fixed deploy for in-house distribution (iOS)

#### &#x20;Deprecated

* Trying to get mac address on Android 6+ will return a constant `02:00:00:00:00:00` due [to provide users with greater data protection](https://developer.android.com/about/versions/marshmallow/android-6.0-changes.html#behavior-hardware-id)

#### &#x20;Known issues

* &#x20;`Class.getCanonicalName()` doesn't return the canonical name, but defaults to `Class.getName()`


# Roadmap

April to June 2020

## Overview

Our roadmap shares our current **focus**: what we are presently working on and what is our scope for **this quarter**. It is a reflection of our ongoing strategic plan, so content *can be changed at any time*, due to **users** demands or strategic impact for business.

## What's coming?

Please, feel free to contribute with your questions or suggestions for each topic via [GitHub](https://github.com/TotalCross/totalcross/issues?q=is%3Aissue+is%3Aopen+label%3AFeature). We have lively discussions happening there.

### Highlights

#### External and native libraries

One of TotalCross developers most requested features is the possibility of using native and external libraries within their applications. This functionality is extremely important for several reasons, among them being able to use serial ports like RS232, access peripherals, and perform hardware analysis. It is our number one priority.

To implement this, we divided it into two macro activities:&#x20;

* create a new method based on the [runtime.exec of java](https://docs.oracle.com/javase/7/docs/api/java/lang/Runtime.html#exec\(java.lang.String\));&#x20;
* Improve **TCNI** for community use;

{% hint style="info" %}
TCNI is a foreign function interface programming framework that enables TotalCross/Java code running in a Java virtual machine to call and be called by native applications and libraries written in other languages such as C, C ++ and assembly.)
{% endhint %}

Click here to reach this topic on [GitHub](https://github.com/TotalCross/totalcross/issues/1).

#### Organize TCVM, TC Java API and Litebase in different repositories on GitHub

From version 6 [TotalCross SDK is open source](https://github.com/TotalCross/totalcross/). Our goal is to make contributing the simplest, facilitating the understanding of what makes up the TC SDK.

Click here to reach this topic on [GitHub](https://github.com/TotalCross/totalcross/issues/2).

#### **Nightly builds**

*Continuous integration* is an important point and we are working to implement it more and more.&#x20;

We will start with [nightly builds](https://blog.testproject.io/2019/10/14/what-are-the-benefits-of-having-nightly-builds/), a feature that consists of automatically generating realizations during the night, avoiding wait by TotalCross users for the release of [minor ](https://semver.org/)versions to access implemented fixes and features.

Click here to reach this topic on [GitHub](https://github.com/TotalCross/totalcross/issues/3).

#### Documentation

We know that there is no point in having incredible features if developers don't know they exist and how to use them. So now there is a team of developers focused on producing documentation, guides and articles.&#x20;

Feel free to contribute with your suggestions creating an [issue on GitHub](https://github.com/TotalCross/totalcross/labels/documentation).

### **Others**

Click on the item to be directed to the GitHub discussio&#x6E;**.**

* [Custom Cam; ](https://github.com/TotalCross/totalcross/issues/6)
* [Sharing information between apps for Android and iOS;](https://github.com/TotalCross/totalcross/issues/11)
* [Improve error warnings in the VSCode plugin and CLI;](https://github.com/TotalCross/totalcross/issues/10)
* [Allow using the camera via streaming;](https://github.com/TotalCross/totalcross/issues/9)
* [Add Lambda](https://github.com/TotalCross/totalcross/issues/5);
* Have publics distros of [totalcross-yocto](https://github.com/TotalCross/totalcross/issues/7) and [totalcross-torizon](https://github.com/TotalCross/totalcross/issues/8);
* [Allow registration and login with GitHub on TotalCross](https://github.com/TotalCross/totalcross/issues/4);


# Getting Started

Learn how to install TotalCross and write your first App.

Check the [Getting Started Guide](https://totalcross.com/get-started/).


# First embedded project with TotalCross

Step by step on how to build your first embedded application using TotalCross

## 1. Introduction

Our first embedded project using TotalCross will be a simple but elegant interface to control a GPIO pin, that can be used to light an LED or even a relay that can switch on and off a more potent light bulb. To do that we will be learning how to use TotalCross’ Gpiod component, alongside the Switch, and the ImageControl components. The final result should look like this:

![](/files/-MCX7QiTwQrubsBS_wBi)

![](/files/-MCX7TPP_Da34gtZvXim)

## 2. Assembling and testing the hardware

To understand the Gpiod module it is important to understand the libgpiod, which is an interface to manage GPIO in user space, present at the Linux Kernel since version 4.8. So, to start off, let’s assemble our hardware and try out a few of libgpiod command line tools. You will need the following components:&#x20;

* An LED
* A 220 Ω resistor (or any other value up to 470 Ω)
* A breadboard and jumpers&#x20;

In this example we will be using a Raspberry Pi 3, but you can use any other hardware running a Linux distribution with an ARM microprocessor unit, just pay attention to the board’s pinout configuration. We can see at the [Raspberry documentation](https://www.raspberrypi.org/documentation/usage/gpio/) that the pin 40 can be used as GPIO21 and pin 39 can be used as GND, so the hardware configuration will be as it is shown in the figure below:&#x20;

![Hardware configuration using Raspberry Pi 3](/files/-MCX8vpVrc6tgkrm_yTd)

{% hint style="info" %}
Don’t forget to make sure that the short leg on your LED (which is the negative lead) is connected to the GND
{% endhint %}

After the circuit is assembled, let’s test the LED using the gpioset tool from the libgpiod interface. It is important to know that the GPIO chips are mapped into groups of 32 pins, so if you are using GPIO 68, for example, you would need to access chip 2 and pin 4 (because 32 x 2 + 4 = 68). In our example, Raspberry 3 has only one chip, so let’s use chip 0 and pin 21.&#x20;

{% hint style="info" %}
As a requirement to use the gpioset tools or TotalCross' Gpiod component, you will need to install the libgpiod-dev package at your board, if it is not installed already. This package contains the required static libraries, headers for this component work on your embedded device. To do that, make sure you have an internet connection in your board and run the following command at its console:

```bash
$ sudo apt-get install -y libgpiod-dev
```

{% endhint %}

Access your board’s console via SSH or a serial port and try the following command:&#x20;

```bash
$ gpioset -m wait gpiochip0 21=1
```

You should see that now your LED is on. This command writes a high value to the GPIO and waits for any user input to set the pin back to its original low state. You can check the [libgpiod page](https://github.com/brgl/libgpiod) on github and maybe try out some other commands. If everything worked fine we are now ready to start writing our TotalCross code!&#x20;

## 3. Writing a TotalCross application

### Create a project with the VSCode plugin

{% hint style="info" %}
At this step by step guide we will be using the official TotalCross plugin for Visual Studio Code, but you can work with any other IDE that supports Java and Maven. Check out how to install TotalCross also on Eclipse and IntelliJ at the environment setup section.
{% endhint %}

Before we start, make sure you have installed VSCode and the TotalCross plugin. Then, press **CTRL + SHIFT + P** and find the “TotalCross: Create New Project” option. You can create a new folder to your project called “LightSwitch”, and then enter “com.totalcross” as your GroupId, and “LightSwitch” again as your ArtifactId. Chose the latest TotalCross version, make sure you check the “-linux\_arm” checkbox and press **Enter** to start your new project. Now, if you open src/main/java/com/totalcross folder at VSCode’s navigator, right click the RunLightSwitchApplication.java file and press enter. You should see TotalCross’ simulator in action, which will now display a white background with the “Hello World” label. You can also press **CTRL + F5** to run it.&#x20;

### Adjust the application resolution

The first step is to adjust the application to fit the resolution of your screen. Let’s suppose your device has a 848x480 LCD display. Open the “RunLightSwitchApplication.java” file and enter two additional strings as parameters to the “TotalCrossApplication.run()” method: "/scr" and "848x480". The string following the “/r” parameter contains your TotalCross registration key, so don’t change it. Check out how your display looks now at your simulator. Your file should look like this:&#x20;

```java
package com.totalcross;
 
import totalcross.TotalCrossApplication;
 
public class RunLightSwitchApplication {
   public static void main(String [] args) {
       TotalCrossApplication.run(LightSwitch.class, "/scr", "848x480", "/r", "xxxxxxxxxxxxxxxxxxxxxxxx");
   }
}
```

### Set up the images and colors&#x20;

At the VSCode's Explorer menu, open the tabs “src” then “main”, right click resources, select “New Folder”, and create a folder called “images”. Right click it and select “Open Containing Folder” to open it at your system. There you can add the two png image files we are going to use at this project:&#x20;

{% file src="/files/-MCy2b6cz4Yc3636J30c" %}

{% file src="/files/-MCy2fqHdJsJ-LaRPRLN" %}

Now right click java/com/totalcross, and create a new folder called “util”. Inside it, create two java files: Colors.java and Images.java. Images.java will serve as a helper class to load our image files and return their instances. Add the following code to it: &#x20;

```java
package com.totalcross.util;
import totalcross.ui.image.Image;
import totalcross.ui.dialog.MessageBox;

public class Images {

   public static Image iLightOff, iLightOn;

   public static void loadImages() {

       try {
           iLightOff = new Image("images/light-bulb-off.png");
           iLightOn = new Image("images/light-bulb-on.png");

       } catch (Exception e) {
           MessageBox.showException(e, true);
       }
   }
}
```

In Colors.java, we will define the hex code for the colors used at the project, so add the following code to it:

```java
package com.totalcross.util;

public class Colors {

    public static final int COLOR_DARK_GRAY = 0x303030;
    public static final int COLOR_MEDIUM_GRAY = 0x878787;
    public static final int COLOR_LIGHT_GRAY = 0x565656;

    public static final int COLOR_DARK_YELLOW = 0xF7FC26;
    public static final int COLOR_LIGHT_YELLOW = 0xD7FF8C;
}
```

### Create the UI components

First let’s import all the packages we are going to need at the LightSwitch.java class. Add the following lines to it:&#x20;

```java
package com.totalcross;

import com.totalcross.util.*;
import totalcross.ui.MainWindow;
import totalcross.ui.Switch;
import totalcross.ui.ImageControl;
import totalcross.io.device.gpiod.GpiodChip;
import totalcross.io.device.gpiod.GpiodLine;
import totalcross.ui.event.ControlEvent;
import totalcross.ui.event.PressListener;
import totalcross.util.UnitsConverter;
import totalcross.sys.Settings;
```

Now let’s implement our main application in the LightSwtich.java file. Note that, by default, the class extends MainWindow class. Every TotalCross application must have one class extending it, as it serves as the main interface between our program and the TotalCross virtual machine (TCVM). We will use the constructor method to set the user interface style and set the background color to the application. Add the following lines of code to it:&#x20;

```java
public LightSwitch() {
        setUIStyle(Settings.MATERIAL_UI);
        setBackColor(Colors.COLOR_DARK_GRAY);
    }
```

Then let’s create our UI components at the overriden initUI() method. Create the instances to Switch and ImageControl components, set their attributes, and add them to the main window. To do that, we use the add() method, where we can also specify the component’s position and size at the screen. Also notice that we are using the Images util class we created before to load the images and to give a starting state to our ImageControl component.

```java
private Switch swLightSwitch;
private ImageControl icLight;

@Override
public void initUI() {

        Images.loadImages();
        
        //Create switch components
        swLightSwitch = new Switch();
        
        //Set the colors of the switch's parts
        swLightSwitch.colorBallOn = Colors.COLOR_DARK_YELLOW;
        swLightSwitch.colorBallOff = Colors.COLOR_LIGHT_GRAY;
        swLightSwitch.colorBarOn = Colors.COLOR_LIGHT_YELLOW;
        swLightSwitch.colorBarOff = Colors.COLOR_MEDIUM_GRAY;
        
        //Create image control component with initial light off image
        icLight = new ImageControl(Images.iLightOff);
        icLight.scaleToFit = true;
        
        // Position light bulb at the center of the screen,
        // using the original size of the image
        add(icLight, CENTER, CENTER - UnitsConverter.toPixels(DP + 40), 
                PREFERRED, PREFERRED);

        // Position the switch below the image 
        add(swLightSwitch, CENTER, AFTER, UnitsConverter.toPixels(DP + 150), 
                UnitsConverter.toPixels(DP + 30));
    }
```

Now we are going to create a pressListener and add it to our light switch. A pressListener obejct is an event handler that serves as a callback to any pressing event that happens on a component. With it we can check the switch’s state at each press and, based on that, update our image with the new on or off state. Create the following object at your class:

```java
PressListener onSwitchPressed = new PressListener() {
        @Override
        public void controlPressed(ControlEvent controlEvent) {
            if (swLightSwitch.isOn()) {
                icLight.setImage(Images.iLightOn);
            } else {
                icLight.setImage(Images.iLightOff);
            }
        }
    };
```

And add it to the switch component, inside the "initUI()" method:&#x20;

```java
swLightSwitch.addPressListener(onSwitchPressed);
```

The UI is ready to go! You can run the TC simulator to check the result.

### Add GPIO components

Finally, let’s add the Gpiod component, which will actually drive our GPIOs according to the switch's state. First we need to create both GpiodChip and GpiodLine objects at our LightSwitch class and initialize them at our "initUI()" method with the respective chip and pin number (with the same values we used with the Linux’s libgpiod). We also need to set the pin as an output, with the “requestOutput” method, and set the initial state as low (represented by 0):

```java
private GpiodChip gpioChip;
private GpiodLine pin;

@Override
public void initUI() {

    // Open Gpio chip
    gpioChip = GpiodChip.open(0);

    // Get Gpio line
    pin = gpioChip.line(21);

    // Request line as output and set the initial state to low
    pin.requestOutput("CONSUMER", 0);
    
    ...
```

Then, use the press listener to set values to on and off state:

```java
PressListener onSwitchPressed = new PressListener() {
        @Override
        public void controlPressed(ControlEvent controlEvent) {
            if (swLightSwitch.isOn()) {
                icLight.setImage(Images.iLightOn);
                pin.setValue(1);
            } else {
                icLight.setImage(Images.iLightOff);
                pin.setValue(0);
            }
        }
    };
```

### Deploy the application to your board

{% hint style="info" %}
Make sure you have installed *libgpiod-dev* at your board, as explained at the [Assembling and testing the hardware](https://learn.totalcross.com/documentation/get-started/first-embedded-project-with-totalcross#2-assembling-and-testing-the-hardware) section
{% endhint %}

To deploy the code to your board, first package the application by pressing **CTRL + SHIFT + P** again and choose “TotalCross: Package”. If everything went ok, you can press **CTRL** + **SHIFT** + **P** again and now choose “TotalCross: Deploy\&Run”. Now enter the user for your board (eg. “pi”), the host (the IP address), and the password to it. You can select the default folder for the application to be stored at the host and press enter to start the upload.&#x20;

If everything worked fine, you now should see the application running at your board like this:

![LightSwitch sample in Raspberry Pi 3](/files/-MD22DcfmYNnQoEXcl8A)

You can try out some modifications and upgrades at the code by your own now, and maybe try out some other [Components](https://learn.totalcross.com/documentation/components). If you want to step up your application ever further, check out the [Guides](https://learn.totalcross.com/documentation/guides) tab, where you can find some tips on how to build a more advanced and scalable architecture to your software, and also how to run external applications using TotalCross.&#x20;

### References <a href="#references" id="references"></a>

* [Source code](https://github.com/TotalCross/LightSwitch)

###

###

##


# Components


# Accordion

### Overview

Accordions are used to show and hide text through user interaction.

{% hint style="info" %}
In Totalcross this component is called **`AccordionContainer`**
{% endhint %}

<div align="left"><img src="/files/-L_mvIAVMhoORe5pWnUY" alt=""></div>

### Source Code

{% code title="AccordionSample.java" %}

```java
import totalcross.sys.Settings;
import totalcross.ui.AccordionContainer;
import totalcross.ui.MainWindow;
import totalcross.ui.MultiEdit;
import totalcross.ui.font.Font;
import totalcross.ui.gfx.Color;

public class AccordionSample extends MainWindow {

	public AccordionSample() {
		setUIStyle(Settings.MATERIAL_UI);
		Settings.uiAdjustmentsBasedOnFontHeight = true;
	}

	public void initUI() {
		int gap = (int) (Settings.screenDensity * 20);

		AccordionContainer.Group gr = new AccordionContainer.Group();
		AccordionContainer ac[] = new AccordionContainer[5];
		MultiEdit me[] = new MultiEdit[5];

		for (int i = 0; i < ac.length; i++) {
			ac[i] = new AccordionContainer(gr);
			ac[i].setFont(font.asBold());
			me[i] = new MultiEdit(50, gap / 4);
			me[i].setText("Type here!");
		}

		add(ac[0], CENTER, AFTER + gap * 2, SCREENSIZE + 85, PREFERRED);
		ac[0].setBackForeColors(0xBFDCF7, Color.BLACK);
		ac[0].add(ac[0].new Caption("...the biggest state?"), LEFT, TOP, FILL, PREFERRED);
		ac[0].add(me[0], LEFT + gap * 4, AFTER + gap, FILL, FONTSIZE + 600);
		me[0].transparentBackground = true;
		me[0].setFont(Font.getFont(false, this.getFont().size));

		for (int i = 1; i < ac.length; i++) {
			add(ac[i], CENTER, AFTER + gap / 2, SCREENSIZE + 85, PREFERRED);
			ac[i].setBackForeColors(0xBFDCF7, Color.BLACK);

			switch (i) {
			case 1:
				ac[i].add(ac[i].new Caption("...the most famous forest?"), LEFT, TOP, FILL, PREFERRED);
				break;
			case 2:
				ac[i].add(ac[i].new Caption("...the current president?"), LEFT, TOP, FILL, PREFERRED);
				break;
			case 3:
				ac[i].add(ac[i].new Caption("...the most famous river?"), LEFT, TOP, FILL, PREFERRED);
				break;
			case 4:
				ac[i].add(ac[i].new Caption("...the most famous statue?"), LEFT, TOP, FILL, PREFERRED);
				break;
			}
			ac[i].add(me[i], LEFT + gap * 4, AFTER + gap, FILL, FONTSIZE + 600);
			me[i].setFont(Font.getFont(false, ac[i].getFont().size));
			me[i].transparentBackground = true;
		}
	}

	public int getScreenWidth() {
		return Settings.screenWidth;
	}
}
```

{% endcode %}

### Attributes

| Type    | Name     | Description                            |
| ------- | -------- | -------------------------------------- |
| **int** | **minH** | Minimum height of the closed accordion |

### Methods

| Type            | Name                                           | Description                                                     |
| --------------- | ---------------------------------------------- | --------------------------------------------------------------- |
| **Constructor** | AccordionContainer( )                          | Creates a empty accordion                                       |
| **Constructor** | AccordionContainer(AccordionContainer.Group g) | Creates a list of accordions from the accordion group.          |
| **void**        | collapse( )                                    | Closes the accordion                                            |
| **void**        | collapse(boolean showAnimation)                | Closes the accordion with animation(depending on the parameter) |
| **void**        | expand( )                                      | Open the accordion                                              |
| **void**        | expand(boolean showAnimation)                  | Open the accordion with animation(depending on the parameter)   |
| **int**         | getPreferredHeight( )                          | Returns the accordion´s minimum height                          |
| **boolean**     | isExpanded( )                                  | Retorna true if the accordion is open                           |
| **void**        | onAnimationFinished(ControlAnimation anim)     | This method is called after the animation is finished           |
| **void**        | setPos(int x, int y)                           | Set the accordion´s x and y position                            |

### References

* See also our [quick video tutorial](https://www.youtube.com/watch?v=7fl1GfuKSOw) on how to add other components within an accordion.
* See the [Java Docs](https://rs.totalcross.com/doc/totalcross/ui/Button.html) for more information.


# Aligned Labels

### Overview

Aligned Label is a Container used to align all controls to the maximum width of a set of labels.

{% hint style="info" %}
In Totalcross this component is called **`AlignedLabelContainer`**.
{% endhint %}

<div align="left"><img src="/files/-L_nC89eMCoeDxzy43QP" alt=""></div>

### Source Code

{% code title="AlignedLabelsSample.java" %}

```java
import totalcross.ui.AlignedLabelsContainer;
import totalcross.ui.Button;
import totalcross.ui.ComboBox;
import totalcross.ui.Edit;
import totalcross.ui.Label;
import totalcross.ui.ListBox;
import totalcross.ui.ScrollContainer;
import totalcross.util.UnitsConverter;

public class extends ScrollContainer {
	private int gap = UnitsConverter.toPixels(10 + DP);
	private boolean canInsert = true;
	private ListBox lb;
	private Label output;

	@Override
	public void initUI() {
		uiAdjustmentsBasedOnFontHeightIsSupported = false;
		setBackForeColors(0xF7F7F7, 0x000000);
		setScrollBars(false, true);

		String[] labels = { "Name", "Born date", "Telephone", "Address", "City", "Country" };
		Edit edits[] = new Edit[5];
		edits[0].transparentBackground = true;
		Edit.useNativeNumericPad = true;

		for (int i = 0; i < edits.length; i++) {
			switch (i) {
			case 1:
				edits[i] = new Edit("99/99/9999");
				edits[i].setMode(Edit.NORMAL, true);
				edits[i].setValidChars(Edit.numbersSet);
				edits[i].setKeyboard(Edit.KBD_NUMERIC);
				break;
			case 2:
				edits[i] = new Edit("(99)9999-99999");
				edits[i].setMode(Edit.NORMAL, true);
				edits[i].setValidChars(Edit.numbersSet);
				edits[i].setKeyboard(Edit.KBD_NUMERIC);
				break;
			default:
				edits[i] = new Edit();
			}
		}

		Label title = new Label("This is an AlignedLabelsContainer.\nAll the content will be automatically aligned.",
				CENTER, 0, true);
		title.autoSplit = true;
		add(title, LEFT + gap, TOP + gap, FILL - gap, PREFERRED);

		AlignedLabelsContainer alc = new AlignedLabelsContainer();
		alc.uiAdjustmentsBasedOnFontHeightIsSupported = false;
		alc.labelAlign = RIGHT;

		alc.setInsets(gap, gap, 0, 0);
		alc.setLabels(labels, edits[0].getPreferredHeight());
		add(alc, LEFT, AFTER, FILL, PREFERRED);
		int i;
		for (i = 0; i < edits.length - 1; i++) {
			alc.add(edits[i], LEFT + gap, alc.getLineY(i), FILL - gap, PREFERRED);
		}

		Button btnInsert = new Button("Insert data", (byte) 0);
		btnInsert.setBackForeColors(0x4583d4, 0xFFFFFF);
		alc.add(edits[edits.length - 1], LEFT + gap, alc.getLineY(i), edits[3].getWidth() / 2 - gap / 2, PREFERRED);
		alc.add(btnInsert, RIGHT - gap, CENTER_OF, SAME, PREFERRED, edits[edits.length - 1]);

		ComboBox cbCountry = new ComboBox(new String[] { "Brazil", "USA" });
		alc.add(cbCountry, LEFT + gap, alc.getLineY(++i), SAME, PREFERRED, edits[edits.length - 1]);

		Button btnClear = new Button("CLEAR DATA", (byte) 0);
		alc.add(btnClear, RIGHT - gap, CENTER_OF, SAME, PREFERRED);

		btnInsert.addPressListener(e -> {
			if (canInsert) {
				lb = new ListBox();
				for (int j = 0; j < edits.length; j++)
					lb.add(labels[j] + ": " + edits[j].getText());
				if (cbCountry.getSelectedIndex() != -1)
					lb.add("Country: " + cbCountry.getSelectedItem());
				else
					lb.add("Country: ");

				output = new Label("OUTPUT:");
				output.setFont(font.asBold());
				add(output, CENTER, AFTER);
				add(lb, CENTER, AFTER + gap, SCREENSIZE + 80, PREFERRED);
				canInsert = false;

				scrollToControl(lb);
			} else {
				lb.removeAll();
				for (int j = 0; j < edits.length; j++)
					lb.add(labels[j] + ": " + edits[j].getText());
				if (cbCountry.getSelectedIndex() != -1)
					lb.add("Country: " + cbCountry.getSelectedItem());
				else
					lb.add("Country: ");
			}
			// reposition(); reposition bugando o edit
		});

		btnClear.addPressListener(e -> {

			// Cleaning the labels' content
			for (Edit edit : edits)
				edit.clear();
			cbCountry.setSelectedIndex(-1);
			if (!canInsert) {
				// Cleaning the output
				remove(lb);
				remove(output);
				canInsert = true;
			}
		});
	}
}
```

{% endcode %}

### Attributes

| Type        | Name         | Description                                                                                  |
| ----------- | ------------ | -------------------------------------------------------------------------------------------- |
| **Font**    | childrenFont | Set this member to the font you want to set to the controls that are added to this container |
| **int\[ ]** | foreColors   | Sets an array with the same number of labels and the colors you want to show for each label  |
| **int**     | labelAlign   | The alignment of the labels                                                                  |

### Methods

| ype            | Name                                               | Description                                                                                      |
| -------------- | -------------------------------------------------- | ------------------------------------------------------------------------------------------------ |
| **Construtor** | AlignedLabelsContainer( )                          | Creates a new AlignedLabelsContainer without labels                                              |
| **Construtor** | AlignedLabelsContainer(String\[] labels)           | Creates a new AlignedLabelsContainer with the given labels                                       |
| **Construtor** | AlignedLabelsContainer(String\[] labels, int vgap) | Creates a new AlignedLabelsContainer with the given labels and a vertical gap between the labels |
| **void**       | add(Control c)                                     | Since this is an AlignedLabelsContainer, use this to add a label                                 |
| **int**        | getLineY(int line)                                 | Given a line (staring from 0), returns the y position                                            |
| **void**       | setLabels(String\[ ] labels, int vgap)             | Sets the labels and the extra gap between rows (which may be 0)                                  |

###


# Button

Buttons are an essential way to interact with and navigate through an app, and should clearly communicate what action will occur after the user taps them

## Examples

To adapt the component to the style of the application it is often necessary to change its colors.

![](/files/-M3v9Ca6rb6EyZeslj_d)

```java
package com.totalcross;
import totalcross.ui.gfx.Color;
import totalcross.sys.Settings;
import totalcross.ui.Button;
import totalcross.ui.MainWindow;
public class HelloWorld extends MainWindow {

    private Button btnRed;
    private Button btnGreen;
    private Button btnBlue;
    public HelloWorld(){
        setUIStyle(Settings.MATERIAL_UI);
    }
    @Override
    public void initUI(){
        btnRed = new Button("Red");
        btnRed.setBackForeColors(Color.RED, Color.WHITE);
        add(btnRed, CENTER,CENTER );
        
        btnGreen = new Button("Green");
        btnGreen.setBackForeColors(Color.GREEN, Color.WHITE);
        add(btnGreen, CENTER, AFTER );
        
        btnBlue = new Button("Blue");
        btnBlue.setBackForeColors(Color.BLUE, Color.WHITE);
        add(btnBlue, CENTER,AFTER);
    }
}
```

## Full Button

![](/files/-M3vBHISGuzIDFhmH9Cm)

Make the button the width of the screen.

```java
package com.totalcross;
import totalcross.ui.gfx.Color;
import totalcross.sys.Settings;
import totalcross.ui.Button;
import totalcross.ui.MainWindow;
public class HelloWorld extends MainWindow {

    private Button btnFull;
    
    public HelloWorld(){
        setUIStyle(Settings.MATERIAL_UI);
    }
    @Override
    public void initUI() {
        btnFull = new Button("Full Button");
        btnFull.setBackForeColors(Color.BLUE, Color.WHITE);
        add(btnFull, CENTER, CENTER, PARENTSIZE, PREFERRED);

    }
}
```

## Button shapes

![](/files/-M3vBpdWI4rzPwYfAzNv)

Modify the button edges.

```java
package com.totalcross;
import totalcross.ui.gfx.Color;
import totalcross.sys.Settings;
import totalcross.ui.Button;
import totalcross.ui.MainWindow;
public class HelloWorld extends MainWindow{

    private Button btnRounded;
    private Button btnBorderless;
    private Button btnOutlined;
    
    public HelloWorld(){
        setUIStyle(Settings.MATERIAL_UI);
    }
    @Override
    public void initUI(){
        btnRounded = new Button("Rounded Corners Button", Button.BORDER_ROUND);
        btnRounded.setBackForeColors(Color.BLUE, Color.WHITE);
        add(btnRounded, CENTER, CENTER );

        btnBorderless = new Button("Borderless Button", Button.BORDER_NONE);
        btnBorderless.setBackForeColors(Color.BLUE, Color.WHITE);
        add(btnBorderless, CENTER, AFTER+5);
        
        btnOutlined = new Button("Outlined Button", Button.BORDER_OUTLINED);
        btnOutlined.setBackForeColors(Color.BLUE, Color.WHITE);
        add(btnOutlined, CENTER, AFTER+5);

    }
}
```

## Sizes

![](/files/-M3vCIGdcKcuAtHi5YDC)

Change the buttons sizes.

```java
package com.totalcross;
import totalcross.ui.gfx.Color;
import totalcross.sys.Settings;
import totalcross.ui.Button;
import totalcross.ui.MainWindow;
public class HelloWorld extends MainWindow {

    private Button btnLarge;
    private Button btnDefaultSize;
    private Button btnSmall;
    
    public HelloWorld() {
        setUIStyle(Settings.MATERIAL_UI);
    }
    @Override
    public  void  initUI() {
        
        btnLarge = new Button("Large",Button.BORDER_ROUND);
        btnLarge.setBackForeColors(Color.BLUE, Color.WHITE);
        add(btnLarge, LEFT+20, CENTER,btnLarge.getPreferredWidth() <=  48  ? DP +  96: btnLarge.getPreferredWidth(),DP +  54);
        
        btnDefaultSize = new Button("Default",Button.BORDER_ROUND);
        btnDefaultSize.setBackForeColors(Color.BLUE, Color.WHITE);
        add(btnDefaultSize, AFTER+5, CENTER_OF);
        
        btnSmall = new Button("Small",Button.BORDER_ROUND);
        btnSmall.setBackForeColors(Color.BLUE, Color.WHITE);
        add(btnSmall, AFTER+5, CENTER_OF, btnSmall.getPreferredWidth() <=  24? DP +  48  : btnSmall.getPreferredWidth(), DP +  27,btnDefaultSize);
        
    }
}
```

## Button image

![](/files/-M3vCp64V5_G-W8z2CVx)

Add an image to the button.

```java
package com.totalcross;
import totalcross.ui.gfx.Color;
import totalcross.ui.image.Image;
import totalcross.sys.Settings;
import totalcross.ui.Button;
import totalcross.ui.MainWindow;
public class HelloWorld extends MainWindow {

    private Button btnLeftImage;
    
    public HelloWorld() {
        setUIStyle(Settings.MATERIAL_UI);
    }
    @Override
    public void initUI() {
        try {
            Image img = new Image("images/bt_info.png");
            btnLeftImage = new Button("Left Image", img.scaledBy(0.2,0.2), RIGHT,10);
            btnLeftImage.setBackForeColors(Color.BLUE, Color.WHITE);
            add(btnLeftImage, CENTER, AFTER+25);    
        } catch (Exception exception) {
            exception.printStackTrace();
        }       
    }
}
```

{% hint style="warning" %}
Do not forget **to create a folder** called "***images***" inside ***/src/main/resources*** and **save the** [**bt\_info.png**](https://github.com/TotalCross/TCSample/blob/master/src/main/resources/images/bt_info.png) **image inside it** \[images].
{% endhint %}

## Events

Handling events with `addPressListener()` :

```java
package com.totalcross;
import totalcross.ui.gfx.Color;
import totalcross.sys.Settings;
import totalcross.ui.Button;
import totalcross.ui.MainWindow;
public class HelloWorld extends MainWindow {

    private Button btnRed;
    private Button btnGreen;
    private Button btnBlue;
    public HelloWorld(){
        setUIStyle(Settings.MATERIAL_UI);
    }
    @Override
    public void initUI(){
        btn = new Button("Do something");
        btn.setBackForeColors(Color.RED, Color.WHITE);
        btn.addPressListener((event) -> {
            // DO SOMETHING
        })
        add(btn, CENTER,CENTER );
    }
}
```

## Behind the Class

### Attributes

| Type        | Name              | Description                          |
| ----------- | ----------------- | ------------------------------------ |
| **boolean** | Button.CENTRALIZE | Center image and text on the button. |

### Methods

| Type            | Name                                                      | Description                                          |
| --------------- | --------------------------------------------------------- | ---------------------------------------------------- |
| **Constructor** | Button( )                                                 | Creates a simple button                              |
| **Constructor** | Button(Image img)                                         | Creates a simple button with the referred image      |
| **Constructor** | Button(Image img, byte border)                            | Creates a button with the referreds image and border |
| **Constructor** | Button(String text)                                       | Creates a button with the referred text              |
| **Constructor** | Button(String text, byte border)                          | Creates a button with the referreds text and border  |
| **Constructor** | Button(String text, Image img, int textPosition, int gap) | Creates a button with the referred text and image    |
| **Image**       | getImage( )                                               | Return the button image                              |
| **String**      | getText( )                                                | Return the button text                               |
| **Boolean**     | isPressed( )                                              | Return true if button is pressed                     |
| **void**        | press(boolean pressed)                                    | If true, press the button                            |
| **void**        | setBorder(byte border)                                    | Set the button border style                          |
| **void**        | setImage(Image img)                                       | Set the button image                                 |
| **void**        | setPressedColor(int newColor)                             | Return the button text                               |
| **void**        | setText(String text)                                      | Set the button text                                  |
| **void**        | simulatePress( )                                          | Press and depress the button                         |

## **References**

* See also our [quick tutorial video](https://www.youtube.com/watch?v=xjqd3g1IYco) on creating buttons.
* See the [Java Docs](https://rs.totalcross.com/doc/totalcross/ui/Button.html) for more information.


# Check

Box that can be filled with a check. Build powerful forms!

![](/files/-M2Dj27AlPLoUP7-ZBgQ)

## Examples

TotalCross includes a wide range of modifications for your `Check`, use `Control` methods.

```java
package com.totalcross; 

import totalcross.ui.MainWindow; 
import totalcross.ui.gfx.Color; 
import totalcross.ui.Check; 
import totalcross.sys.Settings;

public class HelloWorld extends MainWindow {
    public HelloWorld() {
        setUIStyle(Settings.MATERIAL_UI);
    }
    
    @Override
    public void initUI() {
        try {
            Check red = new Check("Red");
            Check green = new Check("Green");
            Check blue = new Check("Blue");
    
            red.setForeColor(Color.RED);
            green.setForeColor(Color.GREEN);
            blue.setForeColor(Color.BLUE);
    
            add(red, LEFT+100, CENTER-40);
            add(green, LEFT+100, CENTER);
            add(blue, LEFT+100, CENTER+40);
        } catch (Exception exception) {
            // Handle exception
        }
    }
}
```

![](/files/-M2E-gKswipvF1bnQWxA)

## Box and text with different colors

In some situations, it may be necessary to use different colors for the box and the text.

```java
package com.totalcross; 

import totalcross.ui.MainWindow; 
import totalcross.ui.gfx.Color; 
import totalcross.ui.Check; 
import totalcross.sys.Settings;

public class HelloWorld extends MainWindow {
    public HelloWorld() {
        setUIStyle(Settings.MATERIAL_UI);
    }
    
    @Override
    public void initUI() {
        try {
            Check check = new Check("Check!");
    
            check.checkColor = Color.RED;
            check.textColor = Color.BLUE;
    
            add(check, CENTER, CENTER);
        } catch (Exception exception) {
            // Handle exception
        }
    }
}
```

![](/files/-M2E8Vp33jFjljevQxeR)

## Custom left gap

Increase or decrease the spacing between box and text try `check.textLeftGap = 20`

![](/files/-M2ECrafVAko81cz6RSH)

## Responsive text split

Have more responsive texts using `check.autoSplit = true`.  Useful for applications that deal with resizing

## Behind the Class

### Attributes

| Type        | Name        | Description                                                                                 |
| ----------- | ----------- | ------------------------------------------------------------------------------------------- |
| **boolean** | autoSplit   | Set to true to let the Check split its text based on the width every time its width changes |
| **int**     | checkColor  | Set to the color of the check, if you want to make it different of the foreground color     |
| **int**     | textColor   | Sets the text color of the check                                                            |
| **int**     | textLeftGap | Set gap size between check box and text                                                     |

### Methods

| Type            | Name                                           | Description                                                                |
| --------------- | ---------------------------------------------- | -------------------------------------------------------------------------- |
| **Constructor** | Check(String Text)                             | Creates a check control displaying the given text                          |
| **Boolean**     | isChecked( )                                   | Returns the checked state of the control                                   |
| **String**      | getText( )                                     | Gets the text displayed in the check                                       |
| **void**        | setChecked(boolean checked)                    | Sets the checked state of the control                                      |
| **void**        | setChecked(boolean checked, boolean sendPress) | Sets the checked state of the control, and send the press event if desired |
| **void**        | setText(String text)                           | Sets the text that is displayed in the check                               |
| **void**        | split(int maxWidth)                            | Splits the text to the given width                                         |

## **References**

* See the [JavaDocs](https://rs.totalcross.com/doc/totalcross/ui/Check.html) for more information.


# ComboBox

### Overview

It is a compressed checkbox that, when clicked, expands, allowing the user to choose an item from several possible options

<div align="left"><img src="/files/-LaWDxt6fS3t0h4n4l38" alt=""></div>

{% hint style="info" %}
This sample code is only from the ComboBox, to see the complete sample, including the ListBox, go to [github](https://github.com/TotalCross/TCSample/blob/master/src/main/java/totalcross/sample/components/ui/ComboListSample.java).
{% endhint %}

### Source Code

{% code title="ComboBoxSample.java" %}

```java
import totalcross.sys.Settings;
import totalcross.ui.ComboBox;
import totalcross.ui.Label;
import totalcross.ui.ScrollContainer;
import totalcross.ui.dialog.MessageBox;

public class ComboBoxSample extends ScrollContainer {

	private ComboBox simpleComboBox;
	private ComboBox popupComboBox;

	private int gap = (int) (Settings.screenDensity * 20);

	@Override
	public void initUI() {
		try {
			setScrollBars(false, true);
			setBackForeColors(0xF7F7F7, 0x000000);

			String[] items = { "One", "Two", "Three", "Four", "Five", "Six", "Seven", "Eight", "Nine", "Ten" };

			Label lbCombos = new Label("Combos", CENTER);
			lbCombos.setFont(lbCombos.getFont().asBold());
			add(lbCombos, LEFT + gap, AFTER + gap * 2, FILL - gap, PREFERRED);

			ComboBox.usePopupMenu = false;
			simpleComboBox = new ComboBox(items);
			simpleComboBox.caption = "Numbers with Dropdown";
			simpleComboBox.setForeColor(0x000000);

			add(simpleComboBox, LEFT + gap, AFTER + gap / 2, FILL - gap, PREFERRED);

			ComboBox.usePopupMenu = true;
			popupComboBox = new ComboBox(items);
			popupComboBox.caption = "Numbers with Popup";
			popupComboBox.setForeColor(0x000000);

			add(popupComboBox, LEFT + gap, AFTER + gap / 2, FILL - gap, PREFERRED);

		} catch (Exception e) {
			MessageBox.showException(e, true);
		}
	}
}
```

{% endcode %}

### Attributes

| Type        | Name         | Description                                                                                                                                                                                                                       |
| ----------- | ------------ | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| **int**     | checkColor   | Changing the value of this variable will change the color of the RadioButton, that only appears in the Android environment, or the color of the arrow in other evironments where MaterialUI is enabled                            |
| **Boolean** | enableSearch | When the number of items in a ComboBox is greater than 10, an area above the popup list is intended for item searching. By default, the value of this attribute is true, set it to false if you do not want this item search area |
| **String**  | popupTitle   | Changes the popup list title                                                                                                                                                                                                      |
| **Boolean** | usePopMenu   | Assign true to this variable before instanciate a new Combobox to show items in a popup window menu.                                                                                                                              |

### Methods

| Type            | Name                                            | Description                                                                                                                                                                                                                                     |
| --------------- | ----------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| **Constructor** | ComboBox( )                                     | Creates an empty ComboBox                                                                                                                                                                                                                       |
| **Constructor** | ComboBox(Object\[ ] items)                      | Creates a ComboBox with the given items                                                                                                                                                                                                         |
| **Constructor** | ComboBox(ListBox userListBox)                   | Creates a ComboBox with a popup list containing the given ListBox. You can create a class that extends a ListBox to draw the items by yourself and then pass it as parameter to this constructor, so the popup list will use your class instead |
| **Constructor** | ComboBox(ComboBoxDropDown userPopList)          | Creates a ComboBox with the given PopList                                                                                                                                                                                                       |
| **void**        | add(Object item)                                | Adds an object to the Listbox                                                                                                                                                                                                                   |
| **void**        | add(Object\[ ] items)                           | Adds an array of Objects to the Listbox                                                                                                                                                                                                         |
| **void**        | clear( )                                        | Resets the selected index to the value of the defaultClearValueInt attribute; the default value is 0                                                                                                                                            |
| **Object**      | getItemAt(int i)                                | Get the object at the given index                                                                                                                                                                                                               |
| **Object\[ ]**  | getItems( )                                     | Returns all items in this ComboBox                                                                                                                                                                                                              |
| **ListBox**     | getListBox( )                                   | Returns the ListBox used to show the items of the ComboBox                                                                                                                                                                                      |
| **Object**      | getSelectedItem( )                              | Returns the selected item of the ListBox                                                                                                                                                                                                        |
| **void**        | remove(int itemIndex)                           | Removes an object from the Listbox at the given index                                                                                                                                                                                           |
| **void**        | remove(Object item)                             | Removes an object from the Listbox                                                                                                                                                                                                              |
| **void**        | removeAll( )                                    | Empties the items of the ComboBox                                                                                                                                                                                                               |
| **void**        | setItemAt(int i, Object s)                      | Sets the object at the given index                                                                                                                                                                                                              |
| **void**        | setSelectedIndex(int i)                         | Select the given index                                                                                                                                                                                                                          |
| **void**        | setSelectedIndex(int i, boolean sendPressEvent) | Select the given index, and optionally sends a PRESSED event                                                                                                                                                                                    |
| **void**        | setSelectedItem(Object name, boolean sendPress) | Select an item, and optionally sends a PRESSED event                                                                                                                                                                                            |

### References

* See also our [quick tutorial video](https://www.youtube.com/watch?v=UN67cUHuD7M) on creating Combo and List Box.
* See the [Java Docs](https://rs.totalcross.com/doc/totalcross/ui/Button.html) for more information.


# Dynamic Scroll

### Overview <a href="#overview" id="overview"></a>

Scroll is a specialized type of Scroll Container intended for high performance where hundreds or thousands of views need to be displayed in a scrollable list.​

{% hint style="info" %}
In Totalcross this component is called **`DynamicScrollContainer`**
{% endhint %}

![](/files/-LaWGAtAT5cEzA9mr2s0)

{% hint style="info" %}
Because it is a more complex example, which does not only involve the creation of the interface, we have a simpler and more direct example. To access the complete example, just go to our [github](https://github.com/TotalCross/TCSample/blob/master/src/main/java/totalcross/sample/components/ui/DynScrollContainerSample.java).
{% endhint %}

### Source Code <a href="#source-code" id="source-code"></a>

{% code title="DynScrollContainerSample.java" %}

```java
// Creating and positioning the DynamicScrollContainer
vsc = new DynamicScrollContainer();
vsc.setBackColor(Color.WHITE);
vsc.setBorderStyle(BORDER_SIMPLE);
add(vsc, LEFT + gap, AFTER + gap*2, FILL - gap, FILL - gap*2);
// Adding views to the DynamicScrollContainer
DynSCTestView view = new DynSCTestView(array[i], font);
view.height = Settings.screenHeight / 20;
datasource.addView(view);
```

{% endcode %}

### Methods

| Type                                    | Name                                                                 | Description                                                                                                   |
| --------------------------------------- | -------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------- |
| **Constructor**                         | DynamicScrollContainer( )                                            | Creates a empty DynamicScrollContainer.                                                                       |
| **Constructor**                         | DynamicScrollContainer(DynamicScrollContainer.DataSource datasource) | Creates a DynamicScrollContainer that sets the referred datasource                                            |
| **DynamicScrollContainer.AbstractView** | getTopMostVisibleView( )                                             | Return the top most visible view                                                                              |
| **Boolean**                             | isViewVisible(DynamicScrollContainer.AbstractView view)              | Return true if the view is visible                                                                            |
| **Boolean**                             | scrollContent(int dx, int dy, boolean fromFlick)                     | Scroll the DynamicScrollContainer to the referred position. If the boolean is true, it does a flick animation |
| **void**                                | scrollToView(DynamicScrollContainer.AbstractView view)               | Scroll the DynamicScrollContainer to the view                                                                 |
| **void**                                | setDataSource(DynamicScrollContainer.DataSource datasource)          | Set the DataSource                                                                                            |
| **void**                                | stopFlick()                                                          | Stops any flick animation                                                                                     |


# Edit

An Edit is a field used to show and alter texts. Also known as UITextField on Swift and input on HTML. There also is some variations, like Outlined Edit, Calculator Edit, Password Edit, etc.

## Examples

![](/files/-M3vG2sK2-LjmdIBfwGZ)

In most applications is necessary to remove the background from the object and change the color of the element so that it is better viewed.

```java
package com.totalcross;
import totalcross.sys.Settings;
import totalcross.ui.Edit;
import totalcross.ui.MainWindow;
import totalcross.ui.dialog.MessageBox;
import totalcross.ui.gfx.Color;
import totalcross.util.UnitsConverter;

public class HelloWorld extends MainWindow {
    private Edit simpleEdit;
    private int GAP = UnitsConverter.toPixels(DP +  15);

    public HelloWorld(){
        setUIStyle(Settings.MATERIAL_UI);
    }  

    @Override
    public void initUI(){
        try{
            simpleEdit = new Edit();
            simpleEdit.caption = "Simple Edit";
            simpleEdit.transparentBackground = true;
            simpleEdit.captionColor = Color.RED;
            simpleEdit.setForeColor(Color.RED);

            add(simpleEdit, LEFT + GAP, AFTER + GAP);
        } catch (Exception e) {
            MessageBox.showException(e, true);
        }
    }
}
```

## Numeric edit

![](/files/-M3vGb1HsgprOXCN95DZ)

In some situations, entry should be limited to numbers.

```java
package com.totalcross;
import totalcross.sys.Settings;
import totalcross.ui.Edit;
import totalcross.ui.MainWindow;
import totalcross.ui.dialog.MessageBox;
import totalcross.util.UnitsConverter;

public class HelloWorld extends MainWindow {

    private Edit numericEdit;
    private Edit calculatorEdit;
    private int GAP = UnitsConverter.toPixels(DP +  15);
    
    public HelloWorld(){
        setUIStyle(Settings.MATERIAL_UI);
    }  
    @Override
    public void initUI(){
        try{
            numericEdit = new Edit();
            numericEdit.caption =  "NumericBox Edit";
            numericEdit.setMode(Edit.CURRENCY);
            numericEdit.setKeyboard(Edit.KBD_NUMERIC);  
            add(numericEdit, LEFT + GAP, AFTER + GAP);
            
            calculatorEdit =  new  Edit();
            calculatorEdit.caption =  "Calculator Edit";
            calculatorEdit.setMode(Edit.CURRENCY, true);
            add(calculatorEdit, LEFT + GAP, AFTER + GAP);
        } catch (Exception  ee) {
            MessageBox.showException(ee, true);
        }
    }
}
```

## Password Edit

![](/files/-M3vHKyoxFu7thisCOaT)

If the entry is a password, it should not be possible to see it.

```java
package com.totalcross;
import totalcross.sys.Settings;
import totalcross.ui.Edit;
import totalcross.ui.MainWindow;
import totalcross.ui.dialog.MessageBox;
import totalcross.util.UnitsConverter;

public class HelloWorld extends MainWindow {
    private Edit passwordShowEdit;
    private Edit passwordHidenEdit;
    private int GAP = UnitsConverter.toPixels(DP +  15);

    public HelloWorld(){
        setUIStyle(Settings.MATERIAL_UI);
    }  
    @Override
    public void initUI(){
        try{
            passwordShowEdit = new Edit();
            passwordShowEdit.caption = "Password Edit (last character is shown)";
            passwordShowEdit.setMode(Edit.PASSWORD);
            add(passwordShowEdit, LEFT + GAP, AFTER + GAP);
            
            passwordHidenEdit =  new  Edit();
            passwordHidenEdit.caption =  "Password Edit (all characters are hidden)";   
            passwordHidenEdit.setMode(Edit.PASSWORD_ALL);
            add(passwordHidenEdit, LEFT + GAP, AFTER + GAP);
        }catch (Exception  ee) {
            MessageBox.showException(ee, true);
        }
    }
}
```

## Edit shapes

![](/files/-M3vHeV-a7bZ2NmzIct4)

To receive different input formats, which are not predefined in TotalCross.

```java
package com.totalcross;
import totalcross.sys.Settings;
import totalcross.ui.Edit;
import totalcross.ui.MainWindow;
import totalcross.ui.dialog.MessageBox;
import totalcross.util.UnitsConverter;

public class HelloWorld extends MainWindow {
    private Edit calendarEdit;
    private Edit timerEdit;
    private Edit maskedEdit;
    private int GAP = UnitsConverter.toPixels(DP +  15);

    public HelloWorld(){
        setUIStyle(Settings.MATERIAL_UI);
    }  

    @Override
    public void initUI(){
        try{
            calendarEdit = new Edit("99/99/99");
            calendarEdit.caption =  "Calendar Edit";
            calendarEdit.setMode(Edit.DATE, true);
            add(calendarEdit, LEFT + GAP, AFTER + GAP);

            timerEdit = new Edit("99"  + Settings.timeSeparator +  "99"  + Settings.timeSeparator +  "99");
            timerEdit.caption = "TimeBox Edit (24-hour format)";
            timerEdit.setValidChars("0123456789AMP");
            timerEdit.setMode(Edit.NORMAL, true);
            timerEdit.setKeyboard(Edit.KBD_TIME);
            add(timerEdit, LEFT + GAP, AFTER + GAP);

            maskedEdit = new Edit("999.999.999-99");
            maskedEdit.caption = "Masked Edit (999.999.999-99)";
            maskedEdit.setMode(Edit.NORMAL, true);
            maskedEdit.setValidChars(Edit.numbersSet);
            add(maskedEdit, LEFT + GAP, AFTER + GAP);
        }catch (Exception  ee){
            MessageBox.showException(ee, true);
        }
    }
}
```

## Behind the Class

### Attributes

| Type        | Name                 | Description                                                                                                                                                                            |
| ----------- | -------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| **String**  | clearValueStr        | stores the value that will be used by the clear() method to switch texts                                                                                                               |
| **Byte**    | captalise            | <p>used to modify the the letter case from the text within the Edit:</p><ul><li>ALL\_NORMAL: normal case</li><li>ALL\_LOWER: all lowercase</li><li>ALL\_UPPER: all uppercase</li></ul> |
| **String**  | caption              | The Edit's placeholder text                                                                                                                                                            |
| **boolean** | forceBackgroundColor | forces the edit tu use the background color on it, must be used with UIColors.sameColors setted to **true**                                                                            |

### Methods

| Type            | Name                              | Description                                                                                                                                                                                                                                                                              |
| --------------- | --------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| **Constructor** | Edit( )                           | Creates a box for user input                                                                                                                                                                                                                                                             |
| **Constructor** | Edit(String mask)                 | Creates a box for user input, but with a mask                                                                                                                                                                                                                                            |
| **void**        | setMode(byte mode)                | Used to change the mode value to one of the accepted ones by the mode constants, without masking. To enable masking, you should use the setMode(byte mode, boolean maskedEdit) method, and pass the mode you wish and true on the second parameter                                       |
| **void**        | setEditable(boolean on)           | will enable or disable the Edit. Can be used as a way to make sure the user don't modify something that was already saved on server and can't be modified without proper authorization                                                                                                   |
| **String**      | getText( )                        | Returns the text within the Edit, without care for the mask. It's important to note that in the case where there is mask, the characters from the mask will come with the user input, to get only the user input you should be using the getTextWithoutMask() method to recover the text |
| **void**        | setMaxLength()                    | Is used to limit the characters number the user can digit on the text field                                                                                                                                                                                                              |
| **void**        | setPrediction(boolean prediction) | Is used to set if there should or not exist prediction on this Edit, it is, however set to true by default.                                                                                                                                                                              |

### References

* See also our [quick tutorial video](https://www.youtube.com/watch?v=QIBNLwn8uYU) on creating Edits.
* See the [Java Docs ](https://rs.totalcross.com/doc/totalcross/ui/Edit.html)for more information.


# Floating Button

### Overview

Floating Button is a circular floating button that keeps fixed on its initial position and, usually, is used for the main action of the screen.

<div align="left"><img src="/files/-LaWO8y6A7vRQGrXGtbv" alt=""></div>

### Source Code

{% code title="FloatButton" %}

```java
Image ic = null;
try {
  ic = new Image("images/floatbtn.png");
} catch (IOException e) {
  e.printStackTrace();
} catch (ImageException e) {
  e.printStackTrace();
}
FloatingButton floatbutton = new FloatingButton(ic);
floatbutton.setBackColor(Color.getRGB(109, 156, 232));
floatbutton.setIconSize(30);
add(floatbutton, RIGHT-40, BOTTOM-40);

```

{% endcode %}

{% hint style="warning" %}
Do not forget **to create a folder** called "***images***" inside ***/src/main/resources*** and **save the** [**floatbtn.png**](https://github.com/TotalCross/TCSample/blob/master/src/main/resources/images/floatbtn.png) **image inside it** \[images].
{% endhint %}

### Métodos

| Type            | Name                                  | Description                                                 |
| --------------- | ------------------------------------- | ----------------------------------------------------------- |
| **Constructor** | FloatingButton( )                     | Creates a Floating Button with a predefined icon.           |
| **Constructor** | FloatingButton(Image foregroundImage) | Creates a Floating Button with setting the icon.            |
| **void**        | setIcon(image foregroundImage)        | Sets the Floating Button icon.                              |
| **void**        | setIconSize(int iconsize)             | Sets the Floating Button icon size.                         |
| **Image**       | getIcon( )                            | Returns the Image that represents the Floating Button icon. |
| **int**         | getIconSize( )                        | Returns the size of the Floating Button icon.               |


# Gpiod

This library serves to control the digital pins of the embedded GPIO.

## Requirements

In order to execute Gpiod methods at your embedded device, you will need to have the libgpiod-dev package installed in your board. You can do that by entering the following command at the device's terminal:

```java
$ sudo apt-get install libgpiod-dev
```

## Output

To activate and deactivate any external component the embedded board is to change the value of the GPIO pin that will activate it.

![](/files/-M53PjixdUGrq7TOt6zW)

![](/files/-M53ZeAFklMIWROr_hgp)

```java
package com.totalcross.DocRpi;
import totalcross.ui.MainWindow;
import totalcross.ui.event.ControlEvent;
import totalcross.ui.event.PressListener;
import totalcross.ui.gfx.Color;
import totalcross.ui.Button;
import totalcross.io.device.gpiod.GpiodChip;
import totalcross.io.device.gpiod.GpiodLine;
import totalcross.sys.Settings;

public class DocRpi extends MainWindow {
    // Integers to store state of each LED pin, 0 (LOW) and 1 (HIGH)
    private int    stt;
    // Buttons to control
    private Button btn;
    public DocRpi(){
        setUIStyle(Settings.MATERIAL_UI);
    }
    @Override
    public void initUI(){
        // Board Setup
        GpiodChip gpioChip = GpiodChip.open(0); // GIPIO bus
        GpiodLine pin = gpioChip.line(21);      //
        // Set LED pins as outputs and default value stt
        pin.requestOutput("CONSUMER",stt);
        // The TotalCross button:
        btn = new Button("Pin");                                    // Button instantiation
        // without text
        btn.setBackColor(Color.RED);                                // Set background color (red)
        btn.addPressListener(new PressListener(){                  // Press event listener
            @Override
            public void controlPressed(ControlEvent controlEvent) {
                stt = 1 - stt;                                      // Invert pin state 
                pin.setValue(stt);                                  // Set value (HIGH or LOW)
            }
        });
        add(btn, CENTER, CENTER);  
    }
}                               
```

## Input

In several embedded applications, it is necessary to receive digital signal from an external component such as sensors or even to activate another component indirectly.

![](/files/-M53_xDGWMdtoXky1PqM)

```java
package com.totalcross.DocRpi;
import totalcross.ui.MainWindow;
import totalcross.ui.event.ControlEvent;
import totalcross.ui.event.PressListener;
import totalcross.ui.gfx.Color;
import totalcross.ui.Button;
import totalcross.io.device.gpiod.GpiodChip;
import totalcross.io.device.gpiod.GpiodLine;
import totalcross.sys.Settings;
import totalcross.sys.Vm;

public class DocRpi extends MainWindow{
    // Integers to store state of each LED pin, 0 (LOW) and 1 (HIGH)
    private int stt;
    // Buttons to control 
    private Button btn;
    public DocRpi(){
        setUIStyle(Settings.MATERIAL_UI);   
    }
    @Override
    public void initUI(){
    
        // Board Setup
        GpiodChip gpioChip = GpiodChip.open(0); // GIPIO bus
        GpiodLine pin = gpioChip.line(21);      //
        // Set LED pins as outputs and default value stt
        pin.requestOutput("CONSUMER", stt);
        GpiodLine pinPushButton = gpioChip.line(22);
        // Set Reset pin as input
        pinPushButton.requestInput("CONSUMER");
        new Thread(){
            @Override
            public void run(){
                while(true){
                    if(pinPushButton.getValue() == 1){//check pin status
                        stt = 1 - stt;          // Invert pin state 
                        pin.setValue(stt);      // Set value (HIGH or LOW)
                    }
                    Vm.sleep(200);
                 } 
             }
         }.start();
    }
}

```

## Behind the Class

### Methods

| Type            | Name                                             | Description                                             |
| --------------- | ------------------------------------------------ | ------------------------------------------------------- |
| **Constructor** | open(int chip)                                   | Defines which GPIO bus will be used.                    |
| **Construtor**  | line(int pin)                                    | Defines which pin of GPIO bus will be used.             |
| **Void**        | requestOutput(String consumer, int defaultValue) | Names the pin, defines as output and the initial value. |
| **Void**        | setValue(int value)                              | Changes pin value.                                      |
| **Void**        | requestInput(String consumer)                    | Names the pin and defines as input.                     |
| **Int**         | getValue()                                       | Returns pin status                                      |


# Grid

### Overview

Grid is a control that contains a list organized by columns, where each column can receive an individual size and an alignment.

### Source Code

```java
import totalcross.sys.Settings;
import totalcross.ui.Button;
import totalcross.ui.Grid;
import totalcross.ui.MainWindow;
import totalcross.ui.dialog.MessageBox;
import totalcross.util.UnitsConverter;
import java.util.ArrayList;

public class GridSample extends MainWindow {

    private final int H = 225;
    private ArrayList<User> users = new ArrayList<>();
    private Grid grid;
    private Button loadButton;
    private int GAP = UnitsConverter.toPixels(DP + 8);
    
    public GridSample(){
        setUIStyle(Settings.Material);
    }

    @Override
    public void initUI() {
        String[] gridCaptions = { "Name", "Phone", "Email" };
        int gridWidths[] = { -35, -35, -30 };
        int gridAligns[] = { LEFT, LEFT, LEFT };

        grid = new Grid(gridCaptions, gridWidths, gridAligns, false);
        grid.verticalLineStyle = Grid.VERT_LINE;

        loadButton = new Button("Load");

        add(grid, LEFT + GAP, TOP + GAP, FILL - GAP, FILL - GAP * 9);
        add(loadButton, LEFT + GAP, BOTTOM - GAP, FILL - GAP, PREFERRED);

        loadButton.addPressListener( e -> {

            for (int i = 0; i < 5; i++) {
                users.add(new User("Joao ","99999999","joao@j.com","12345678"));
            }

            if (users.size() > 0) {
                String items[][] = new String[users.size()][3];
                for (int i = 0; i < users.size(); i++) {
                    User user = users.get(i);
                    items[i] = new String[] { user.getName(), user.getPhone(), user.getMail() };
                }
                grid.setItems(items);
            } else {
                MessageBox mb = new MessageBox("Message", "No registered users.", new String[] { "Close" });
                mb.popup();
            }
        });
    }

    public class User {

        private String name;
        private String phone;
        private String mail;
        private String password;

        public User() {

        }

        public User(String name, String phone, String mail, String password) {
            this.name = name;
            this.phone = phone;
            this.mail = mail;
            this.password = password;
        }

        public String getName() {
            return name;
        }
        public void setName(String name) {
            this.name = name;
        }
        public String getPhone() {
            return phone;
        }
        public void setPhone(String phone) {
            this.phone = phone;
        }
        public String getMail() {
            return mail;
        }
        public void setMail(String mail) {
            this.mail = mail;
        }
        public String getPassword() {
            return password;
        }
        public void setPassword(String password) {
            this.password = password;
        }

    }
}


```

### Methods

| Type                                                                                                                                                                                                  | Name                                                                         | Description                                                                                                                        |
| ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ---------------------------------------------------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------- |
| **Constructor**                                                                                                                                                                                       | Grid(String\[] captions, int\[] widths, int\[] aligns, boolean checkEnabled) | <p>Captions for the columns. Cannot be null;</p><p></p><p>Widths of the columns. If the total width is less than the grid's width, |
| the last column will fill until the grid width;</p><p></p><p>Alignment of information on the given column;</p><p></p><p>checkEnabled is True if you want the multi-selection check column;</p><p></p> |                                                                              |                                                                                                                                    |
| **Constructor**                                                                                                                                                                                       | Grid(String\[] captions, boolean checkEnabled)                               | <p>Captions for the columns;<br>checkEnabled is True if you want the multi-selection check column;</p><p></p>                      |
| **Void**                                                                                                                                                                                              | setItems(String\[]\[] items)                                                 | Sets the grid items to be displayed.                                                                                               |
| **Void**                                                                                                                                                                                              | setDataSource(DataSource ds, int nrItems)                                    | Sets the data source of this grid to be the given one.                                                                             |
| **Void**                                                                                                                                                                                              | add(String\[] item)                                                          | Add a new line.                                                                                                                    |
| **Void**                                                                                                                                                                                              | add(String\[] item, int row)                                                 | Add a new line at the given index position of the grid.                                                                            |

‌

### References <a href="#references" id="references"></a>

* See the [github](https://github.com/TotalCross/TCSample/blob/master/src/main/java/totalcross/sample/components/ui/GridSample.java) sample.
* See the [Java Docs](https://rs.totalcross.com/doc/totalcross/ui/Grid.html) for more information.


# GridContainer

### Overview

Is a class that uses grid layout, where each cell is a container.\
To use as cell you need to create a class that extends from GridContainer.Cell.

{% hint style="warning" %}
This component only works until version 4.3.8.
{% endhint %}

### Source Code

```java
add(gc = new GridContainer(GridContainer.HORIZONTAL_ORIENTATION),LEFT,TOP,FILL,FILL);
   gc.setBackColor(Color.WHITE);
   Flick f = gc.getFlick();
   f.shortestFlick = 1000;
   f.longestFlick = 6000;
   gc.setPageSize(linhas,colunas);
   gc.setRowsPerPage(linhasPorPagina);
   Celula []cels = new Celula[TOTAL_ITEMS];
   for (int i = 0; i < cels.length; i++)
      cels[i] = new Celula(i);
   gc.setCells(cels);
```

### Construtor

```java
GridContainer(int orientation){}
```

Constructs a GridContainer with the given orientation

### Methods

| Modifier and Type | Method                                 | Description                                                                                                |
| ----------------- | -------------------------------------- | ---------------------------------------------------------------------------------------------------------- |
| Flick             | getFlick()                             | Returns the flick attached to the ScrollContainer.                                                         |
| void              | initUI()                               | Called to initialize the User Interface of this container.                                                 |
| void              | onColorsChanged(boolean colorsChanged) | Called after a setEnabled, setForeColor and setBackColor and when a control has been added to a Container. |
| void              | onEvent(Event e)                       | Called to process key, pen, control and other posted events.                                               |
| void              | onFontChanged()                        | Called after a setFont                                                                                     |
| void              | setCells(GridContainer.Cell\[] cells)  | Sets the cells of this GridContainer.                                                                      |
| void              | setPageSize(int cols, int rows)        | Sets the page size in columns and rows.                                                                    |
| void              | setRowsPerPage(int rpp)                | Sets the rows per page.                                                                                    |

### References

* See the [Java Docs](https://rs.totalcross.com/doc/totalcross/ui/GridContainer.html) for more information.


# Image

### Overview

An image is a rectangular image that you can draw or copy onto a surface.

Image objects can not be added directly to the user interface because they are not controllers (that is, they do not extend the Control class).

To display an image in the user interface, you need to use a control that best suits your needs, such as ImageControl, Button, or Animation. If you do not want to use any controls, you can draw the image on the screen using the Graphics object.

It is important to note that some transformation methods return a new instance of the image, while others apply to the current instance. To preserve an image with a single frame, use getFrameInstance (0);

To better understand TotalCross's recommended way to use images in your projects, go to [the Colors, Fonts and Images](https://totalcross.gitbook.io/playbook/guideline/colors-fonts-and-images) page in the Guideline To Create Apps section.

<div align="left"><img src="/files/-Laa02_-POBsk7Lfp52E" alt=""></div>

### Source Code

{% code title="ImagImageAnimationSample.java" %}

```java
import totalcross.game.Animation;
import totalcross.sys.Settings;
import totalcross.ui.Button;
import totalcross.ui.ComboBox;
import totalcross.ui.Container;
import totalcross.ui.Label;
import totalcross.ui.dialog.MessageBox;
import totalcross.ui.event.ControlEvent;
import totalcross.ui.event.Event;
import totalcross.ui.gfx.Color;
import totalcross.ui.image.Image;

public class ImageAnimationSample extends Container {
	final int gap = 5;
	private Button btnStartStop;
	private Animation anim;
	private ComboBox cbEffect;
	private int effect;

	@Override
	public void initUI() {
		super.initUI();
		add(btnStartStop = new Button(" Start/Stop "), CENTER, TOP + Settings.screenHeight / 7, SCREENSIZE + 50,
				SCREENSIZE + 10);
		btnStartStop.setBackForeColors(0x4583d4, 0xFFFFFF);

		add(new Label("Effect: ", LEFT, Color.BLACK, false), LEFT + Settings.screenWidth / 5,
				BOTTOM - Settings.screenHeight / 4);

		String[] items = { "normal", "scaledBy", "smoothScaledBy", "getRotatedScaledInstance", "getTouchedUpInstance",
				"changeColors", "fadedInstance", "applyColor2/dither" };
		ComboBox.usePopupMenu = false;
		add(cbEffect = new ComboBox(items), AFTER, BOTTOM - Settings.screenHeight / 4,
				FILL - Settings.screenHeight / 10, PREFERRED);
		cbEffect.setSelectedIndex(0);
		cbEffect.setBackForeColors(0x3861af, 0xFFFFFF);
		cbEffect.fillColor = 0x4583d4;
		next(false);
	}

	@Override
	public void onAddAgain() {
		next(false);
	}

	@Override
	public void onEvent(Event event) {
		switch (event.type) {
		case ControlEvent.PRESSED: {
			if (event.target == cbEffect && effect != cbEffect.getSelectedIndex()) {
				next(true);
			} else if (event.target == btnStartStop) {
				if (anim.isPaused) {
					anim.resume();
				} else {
					anim.pause();
				}
			}
			break;
		}
		}
	}

	/**
	 * shows next frame
	 */
	private void next(boolean changeEffect) {
		try {
			onRemove();
			Image img = new Image("images/alligator.gif");
			effect = cbEffect.getSelectedIndex();
			double scale = Settings.isIOS() ? 1.5 : 2; // ios has less opengl
														// memory
			int scaledcount = Settings.screenWidth / 500;
			System.out.println(scaledcount + " ," + Settings.screenWidth);
			for (int i = 0; i < scaledcount; i++) {
				img = img.scaledBy(scale, scale);
			}
			switch (effect) {
			case 1:
				img = img.scaledBy(scale, scale);
				break;
			case 2:
				img = img.smoothScaledBy(scale, scale);
				break;
			case 3:
				img = img.getRotatedScaledInstance(50, 90, -1);
				break;
			case 4:
				img = img.getTouchedUpInstance((byte) 50, (byte) 100);
				break;
			case 5:
				img.changeColors(0xFF31CE31, 0xFFFF00FF);
				break;
			case 6:
				img = img.getFadedInstance();
				break;
			case 7:
				img.applyColor2(Color.RED);
				img.getGraphics().dither(0, 0, img.getWidth(), img.getHeight());
				break;
			}
			if (Settings.isOpenGL) {
				img.applyChanges();
			}
			anim = new Animation(img, 120);
			anim.pauseIfNotVisible = true;
			add(anim, CENTER, CENTER, PREFERRED, PREFERRED);
			anim.start(Animation.LOOPS_UNLIMITED);
		} catch (Throwable e) {
			MessageBox.showException(e, true);
		}
	}

	@Override
	public void onRemove() {
		if (anim != null) {
			anim.stop();
			remove(anim);
			anim = null;
		}
	}
}
```

{% endcode %}

{% hint style="warning" %}
Do not forget **to create a folder** called "***images***" inside ***/src/main/resources*** and **save the** [**alligator.gif**](https://github.com/TotalCross/TCSample/blob/master/src/main/resources/images/alligator.gif) **image inside it** \[images].
{% endhint %}

### Methods

| Type            | Name                                                          | Description                                                                                                                                                                                                                                                                                                                                                                                                                                                                               |
| --------------- | ------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| **Constructor** | Image(int width, int height)                                  | Creates an Image object with the given width and height. The new image has the same color depth and color map of the default drawing surface.                                                                                                                                                                                                                                                                                                                                             |
| **Constructor** | Image(byte\[] fullDescription)                                | Creates an Image object from the given byte array, which must specify the whole image, including its headers. Use only JPEG or PNG images on the devices (GIF and BMP are supported on the desktop only).                                                                                                                                                                                                                                                                                 |
| **Constructor** | Image(String path)                                            | Attempts to read the contents of the file specified by the given path, creating an Image object from the bytes read. The path given is the path to the image file. The file must be in 2, 16, 256, 24 bpp color compressed (RLE) or uncompressed BMP bitmap format, a PNG file, a GIF file, or a JPEG file. If the image cannot be loaded, an ImageException will be thrown.                                                                                                              |
| **Constructor** | Image(Stream s)                                               | Attempts to read the contents of the given stream, and create an Image object from the bytes read. Loads a BMP, JPEG, GIF, or PNG image from a stream. Note that GIF and BMP are supported only on the desktop. Note that all the bytes of the given stream will be fetched, even those bytes that may follow the image.                                                                                                                                                                  |
| **Boolean**     | isSupported(String filename)                                  | Check if a specific file is supported by the platform at runtime; PNG or JPEG are always supported. GIF and BMP are supported on JavaSE only.                                                                                                                                                                                                                                                                                                                                             |
| **int**         | getWidth( )                                                   | Returns the image width                                                                                                                                                                                                                                                                                                                                                                                                                                                                   |
| **int**         | getHeight( )                                                  | Returns the image height                                                                                                                                                                                                                                                                                                                                                                                                                                                                  |
| **Graphics**    | getGraphics( )                                                | Returns the Graphics object used by this image                                                                                                                                                                                                                                                                                                                                                                                                                                            |
| **void**        | changeColors(int from, int to)                                | change all pixels of the same color by another color                                                                                                                                                                                                                                                                                                                                                                                                                                      |
| **void**        | applyColor(int color)                                         | Applies the given color RGB values to all pixels of this image, preserving the transparent color and alpha channel, if set.                                                                                                                                                                                                                                                                                                                                                               |
| **Image**       | scaledBy(double scaleX, double scaleY)                        | Returns a scaled instance of this image. The new dimensions are calculated based on this image’s dimensions and the given proportions. The algorithm used is the replicate scale: not good quality, but fast. The given values must be > 0                                                                                                                                                                                                                                                |
| **Image**       | smoothScaledBy(double scaleX, double scaleY, int backColor)   | Returns a scaled instance of this image. The new dimensions are calculated based on this image’s dimensions and the given proportions. The given values must be > 0. The transparent pixels are replaced by backColor, which produces a smooth border.                                                                                                                                                                                                                                    |
| **Image**       | getRotatedScaledInstance(int scale, int angle, int fillColor) | Returns a rotated and/or scaled version of this image, where the scale parameter indicates the percentage of scaling to be performe, the angle indicates the rotation angle, expressed in trigonometric degrees and FillColor is the fill color. Do not use this method for scaling only, because the scaling methods are faster. If you need a smooth scale and rotate, scale it first with smoothScaledBy() or getSmoothScaledInstance() and rotate it without scaling (or vice-versa). |
| **Image**       | getTouchedUpInstance(byte brightness, byte contrast)          | Retorna uma instância retocada da imagem, onde o parâmetro brightness indica o brilho(que deve ser entre -128 e 127) e o constrast indica o nível de contraste, que também deve ser entre -128(onde não há contraste) e 127(o nível máximo de contraste)                                                                                                                                                                                                                                  |
| **Image**       | getFadedInstance(int backColor)                               | Returns a touched-up instance of this image with the specified brightness and contrast.                                                                                                                                                                                                                                                                                                                                                                                                   |

### References

* See also our [quick tutorial video](https://www.youtube.com/watch?v=1cZBjr7sg3s) on creating Image Animation sample.
* See the [Java Docs](https://rs.totalcross.com/doc/totalcross/ui/Button.html) for more information.


# ImageControl

### Overview

A control that can show an image bigger than its area and that can be dragged using a pen to show the hidden parts.

Note that, by default, events (and dragging) are disabled. You must call setEventsEnabled to allow dragging.

### Source Code

{% code title="Login TCSample" %}

```java
import java.sql.SQLException;

import totalcross.db.sqlite.SQLiteUtil;
import totalcross.io.IOException;
import totalcross.sample.util.Colors;
import totalcross.sql.PreparedStatement;
import totalcross.sql.Statement;
import totalcross.sys.Settings;
import totalcross.sys.Vm;
import totalcross.ui.Button;
import totalcross.ui.Check;
import totalcross.ui.Container;
import totalcross.ui.Edit;
import totalcross.ui.ImageControl;
import totalcross.ui.ScrollContainer;
import totalcross.ui.dialog.MessageBox;
import totalcross.ui.event.ControlEvent;
import totalcross.ui.event.Event;
import totalcross.ui.gfx.Color;
import totalcross.ui.image.Image;
import totalcross.ui.image.ImageException;
import totalcross.util.InvalidDateException;

public class Login extends ScrollContainer {
	private Edit edPass, edLogin;
	private Check ch;
	private Button btLogin, btRegister;
	private ImageControl ic;
    private SQLiteUtil util;
	
	public void initUI(){
		try {
			setBackForeColors(Colors.BACKGROUND, Colors.ON_BACKGROUND);
			ic = new ImageControl(new Image("images/logo.png"));
			ic.scaleToFit = true;
			ic.centerImage = true;
			add(ic, LEFT, TOP+100, FILL, PARENTSIZE+30);
			
			edLogin = new Edit();
			edLogin.caption = "Login";
			//edLogin.setBackColor(Color.RED);
			add(edLogin, CENTER, AFTER+60, PARENTSIZE+90, PREFERRED+30);
			
			edPass = new Edit();
			edPass.caption = "Password";
			//edPass.setBackColor(Color.RED);
			edPass.setMode(Edit.PASSWORD_ALL);
			add(edPass, SAME, AFTER+70, PARENTSIZE+90, PREFERRED+30);
			
			ch = new Check("Remember Me");
			add(ch, LEFT+86, AFTER+100, PARENTSIZE, PREFERRED+30);
			
			btLogin = new Button("Login");
			btLogin.setBackColor(Color.WHITE);
			add(btLogin, CENTER, AFTER+140, PARENTSIZE+80, PREFERRED+60);
			
			btRegister = new Button("Register Now");
			btRegister.transparentBackground = true;
			btRegister.setBorder(BORDER_NONE);
			add(btRegister, CENTER, AFTER, PARENTSIZE+30, PREFERRED+20);
			btRegister.addPressListener(e -> {Vm.exec("url", "http://www.totalcross.com", 0, true);});
			
			//Creating Database
			util = new SQLiteUtil(Settings.appPath,"database.db");
	        Vm.debug(util.fullPath);
			    
	        Statement st = util.con().createStatement();
			st.execute("create table if not exists person (login varchar(20), password varchar(20))");
			st.close();
		
		} catch (IOException | ImageException | SQLException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
	}
	
	public void onEvent(Event e){
		try{
			switch(e.type){
				case ControlEvent.PRESSED:
					if(e.target == btLogin){
						doInsert();
					}
			}
		}catch(Exception ee){
			MessageBox.showException(ee, true);
		}
	}
	
	private void doInsert() throws SQLException, InvalidDateException, ImageException {
		if (edLogin.getLength() == 0 || edPass.getLength() == 0){
			MessageBox mb = new MessageBox("Message","Please fill all fields!",new String[]{"Close"});
			mb.setBackForeColors(Color.WHITE, Color.BLACK);
			mb.popup();
		}else {
		// simple example of how you can insert data into SQLite..
			String sql = "insert into person values(?,?)";
			PreparedStatement st = util.con().prepareStatement(sql);
			st.setString(1, edLogin.getText());
			st.setString(2, edPass.getText());
			st.executeUpdate();
			st.close();		
			
			MessageBox mbox = new MessageBox(null,"Data inserted successfully!");
			mbox.setBackForeColors(Color.WHITE, Color.BLACK);
			mbox.popup();
			
		}
	}
}

```

{% endcode %}

{% hint style="warning" %}
Do not forget **to create a folder** called "***images***" inside ***/src/main/resources*** and **save the logo**[**.**](https://github.com/TotalCross/TCSample/blob/master/src/main/resources/images/alligator.gif)**png image inside it** \[images].
{% endhint %}

### Methods

| Type            | Name                                        | Description                                                                                                                                                                         |
| --------------- | ------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| **Constructor** | ImageControl(Image img)                     | Constructs an ImageControl using the given image.                                                                                                                                   |
| **Constructor** | ImageControl()                              | Constructs with no initial image. You must set the image with the setImage method.                                                                                                  |
| **void**        | setEventsEnabled(boolean enabled)           | Pass true to enable dragging and events on the image.                                                                                                                               |
| **void**        | setImage(Image img)                         | Sets the image to the given one. If the image size is different, you must explicitly call&#xD; setRect again if you want to resize the control.                                     |
| **void**        | setImage(Image img, boolean resetPositions) | Sets the image to the given one, optionally resetting the image position. If the image size is different, you must explicitly call setRect again if you want to resize the control. |
| **int**         | getImageHeight()                            | Returns the image's height; when scaling, returns the scaled height                                                                                                                 |
| **int**         | getImageWidth()                             | Returns the image's width; when scaling, returns the scaled width.                                                                                                                  |
| **Image**       | getImage()                                  | Returns the current image assigned to this ImageControl.                                                                                                                            |
| **void**        | setBackground(Image img)                    | Sets the given image as a freezed background of this image control.                                                                                                                 |
| **boolean**     | moveTo(int newX, int newY)                  | Moves to the given coordinates, respecting the current moving policy regarding                                                                                                      |

### References

* See the [Java Docs](https://rs.totalcross.com/doc/totalcross/ui/ImageControl.html) for more information.
* See the code on [Github](https://github.com/TotalCross/TCSample/blob/master/src/main/java/totalcross/sample/components/ui/Login.java)


# ImageList

### Overview

This control will have a list of images that will be displayed&#x20;

![](/files/-LeyrJqbpKUUf-3V1HPy)

### Source Code

{% code title="Example Code" %}

```java
import totalcross.io.IOException;
import totalcross.sys.Settings;
import totalcross.ui.ImageList;
import totalcross.ui.MainWindow;
import totalcross.ui.image.Image;
import totalcross.ui.image.ImageException;


public class ImageList extends MainWindow {

    public ImageList(){
        setUIStyle(Settings.Material);
    }

    @Override
    public void initUI() {

        try {
            ImageList imageList = new ImageList();
            imageList.add(new Image("images/logo.png"));
            imageList.add(new Image("images/insta_icon.png"));

            add(imageList, LEFT, TOP);
        } catch (ImageException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

```

{% endcode %}

{% hint style="warning" %}
Do not forget **to create a folder** called "***images***" inside ***/src/main/resources*** and **save the images inside it \[images].**
{% endhint %}

### Methods

| Type            | Name                       | Description                                       |
| --------------- | -------------------------- | ------------------------------------------------- |
| **Constructor** | ImageList()                | Create a new instance                             |
| **Constructor** | ImageList(Object\[] items) | Create a new instance already with a filled array |
| **int**         | getPreferredWidth()        | Returns the preferred Width                       |
| **int**         | getPreferredHeight()       | Returns the preferred height                      |

### References

* See the [Java Docs](https://rs.totalcross.com/doc/totalcross/ui/ImageList.html) for more information.


# Label

This control is used to display static text or a marquee. The label in TotalCross can also display multiple lines of text, separated by the character.

## Examples

![](/files/-M3vetOoMEtP2sg2SqB4)

This is the simplest example for label.&#x20;

```java
package com.totalcross;
import totalcross.sys.Settings;
import totalcross.ui.Label;
import totalcross.ui.MainWindow;

public class LabelSample extends MainWindow  {
    public LabelSample(){
        setUIStyle(Settings.MATERIAL_UI);
        Settings.uiAdjustmentsBasedOnFontHeight= true;
    }

    public void initUI(){
        Label helloWord = new Label("Hello World!");
        //helloWord.setText("text");
        add(helloWord, CENTER, CENTER);
        }
}
```

## Label shape

![](/files/-M3vf7IKgYJr4KzT6Pyt)

Modify the shape of the component.

```java
package com.totalcross;
import totalcross.sys.Settings;
import totalcross.ui.Label;
import totalcross.ui.MainWindow;
import totalcross.ui.gfx.Color;
public class LabelSample extends MainWindow{

    public LabelSample(){
        setUIStyle(Settings.MATERIAL_UI);
        Settings.uiAdjustmentsBasedOnFontHeight =  true;
    }

    public void initUI(){
        Label lb1, lb2, lb3, lb4;
        lb1 = new Label("This is a Simple Label", CENTER);
        lb1.setBackForeColors(Color.BLUE,  Color.WHITE);
        add(lb1, CENTER, CENTER, PARENTSIZE +  70, PREFERRED +  20);

        lb2 = new Label("This is a 3D Label", CENTER);
        lb2.setBackForeColors(Color.BLUE,  Color.WHITE);
        lb2.set3d(true);
        add(lb2, CENTER, AFTER +  20, SAME, SAME);

        lb3 = new Label("This is a Inverted Label", CENTER);
        lb3.setBackForeColors(Color.BLUE,  Color.WHITE);
        lb3.setInvert(true);
        add(lb3, CENTER, AFTER +  20, SAME, SAME);

        lb4 = new Label("This is a Label with a large text and line break", CENTER);
        lb4.setBackForeColors(Color.BLUE,  Color.WHITE);
        lb4.autoSplit = true;
        add(lb4, CENTER, AFTER +  20, SAME, 50);

    }

}
```

## Behind the Class

### Attributes

| Type        | Name      | Description                                                                                 |
| ----------- | --------- | ------------------------------------------------------------------------------------------- |
| **int**     | Align     | Sets the text align as LEFT, RIGHT, CENTER and FILL(justified)                              |
| **boolean** | autoSplit | Set to true to let the label split its text based on the width every time its width changes |

### Methods

| Type            | Name                          | Description                                                                                                                                                          |
| --------------- | ----------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| **Constructor** | Label( )                      | Creates an empty label, using FILL as the preferred width                                                                                                            |
| **Constructor** | Label(String text)            | Creates a label displaying the given text (that may be changed at runtime) using left alignment. Supports inverted text, multiple lines and is scrollable by default |
| **Constructor** | Label(String text, int align) | Like the above, but you can also set the horizontal alignment using one of the constants LEFT, CENTER, RIGHT, or FILL (justified)                                    |
| **void**        | setInvert( )                  | Inverts the back and fore colors                                                                                                                                     |
| **void**        | setHighlighted( )             | Highlights the text by painting the text in all directions with a brighter color, then centered, with the foreground color.                                          |
| **void**        | setHighlightedColor( )        | Sets the color used when highlighting is on                                                                                                                          |
| **void**        | set3d(boolean on)             | Draws the label with a 3d effect                                                                                                                                     |

### **References**

* See the [Label Java Docs ](https://rs.totalcross.com/doc/totalcross/ui/Label.html)for more information.
* See the [Video tutorial](https://www.youtube.com/watch?v=2YiR19jInps)&#x20;


# Material Icons

### Overview

Material Icons are the patterns of icons created by [Google - Material Design](https://blog.totalcross.com/en/material-o-layout-da-google/). They are designed to be used in your Web/iOS/Android projects. \
\
Material Icons are available in a wide variety of densities and sizes, with more than **900 icons**, as well as being Open Code.

{% hint style="info" %}
To use the icons, import the ***`MaterialIcons`*** class:

`import totalcross.ui.icon.MaterialIcons; Icon icon = new Icon(MaterialIcons.values());`
{% endhint %}

<div align="left"><img src="/files/-Laa1PYXjtob_NqxNuAj" alt=""></div>

### Source Code

{% code title="MaterialIconSample.java" %}

```java
import totalcross.sys.Settings;
import totalcross.ui.Container;
import totalcross.ui.MainWindow;
import totalcross.ui.icon.Icon;
import totalcross.ui.icon.MaterialIcons;

public class MaterialIconSample extends MainWindow {

	public MaterialIconSample() {
		setUIStyle(Settings.MATERIAL_UI);
		Settings.uiAdjustmentsBasedOnFontHeight = true;
	}

	public void initUI() {
		final int ICON_WIDTH = 64;

		int cols = (int) (Math.min(Settings.screenWidth, Settings.screenHeight)
				/ (ICON_WIDTH * Settings.screenDensity));
		Container c = new Container() {
			@Override
			public void initUI() {
				for (int i = 0, j = 0; i < MaterialIcons.values().length; i++, j++) {
					Icon icon = new Icon(MaterialIcons.values()[i]);
					icon.setFont(icon.getFont().adjustedBy(10));
					add(icon, (j % cols) == 0 ? LEFT : AFTER, (j % cols) == 0 ? AFTER : SAME, PARENTSIZE + (100 / cols),
							DP + ICON_WIDTH);
				}
				resizeHeight();
			}
		};
		add(c, CENTER, TOP + 100, (int) (cols * ICON_WIDTH * Settings.screenDensity), WILL_RESIZE);
	}


```

{% endcode %}

### **References**

* Learn more about Material Design with [our Blog Post](https://blog.totalcross.com/en/material-o-layout-da-google/).
* Learn more about how [Material Icons](https://material.io/tools/icons/) works.
* See the [TotalCross JavaDocs ](https://rs.totalcross.com/doc/index.html)for more information.


# Material Window

### Overview

Material window is a window with a top bar and a return button that supports slide animations with their entire layout made based on the [Google Material Design](https://blog.totalcross.com/en/material-o-layout-da-google/) specifications.

<div align="left"><img src="/files/-Laa0CRZ2lZOPLmOcGS-" alt=""></div>

{% hint style="info" %}
Because this is a more complex example, they choose to only sample part of the main interface and a call from the Material Window. To see the complete example [click here](https://github.com/TotalCross/TCSample/blob/master/src/main/java/totalcross/sample/components/ui/MaterialWindowSample.java)
{% endhint %}

### Source Code

```java
Button btn1 = new Button("Sign Up");
btn1.setBackForeColors(Colors.P_500, Colors.ON_P_500);
vbox.addControl(btn1);
btn1.addPressListener((e) -> {
    MaterialWindow mw = new MaterialWindow("Sign Up",new Presenter() {
        @Override
        public Container getView() {

            return new Container() {
                @Override
                public void initUI() {
                    //put all the window content here
                }
            };
        }
    });
    mw.popup();
});
Button btn2 = new Button("Sign in");
btn2.setBackForeColors(Colors.P_500, Colors.ON_P_500);
vbox.addControl(btn2);
btn2.addPressListener((e) -> {
    MaterialWindow mw = new MaterialWindow("Sign in",new Presenter() {
        @Override
        public Container getView() {
            return new Container() {
                @Override
                public void initUI() {
                    //put all the window content here 
                    
                }
            };
        }
    });
    mw.popup();
});
```

### Methods

| Type            | Name                                                                              | Description                                                                                                                                                      |
| --------------- | --------------------------------------------------------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| **Constructor** | MaterialWindow(Presenter\<Container> provider)                                    | Creates an MaterialWindow that receives a provider that provides the components to be inserted in the window.                                                    |
| **Constructor** | MaterialWindow(boolean delayInitUI, Presenter\<Container> provider)               | Creates an MaterialWindow, that may have a initUI delay, which receives a provider that provides the components to be inserted in the window                     |
| **Construtor**  | MaterialWindow(String title, boolean delayInitUI, Presenter\<Container> provider) | Creates an MaterialWindow, that may have a initUI delay, with the given title that receives a provider that provides the components to be inserted in the window |
| **void**        | setBarFont(Font f)                                                                | Sets the bar font.                                                                                                                                               |
| **void**        | setTitle(String title)                                                            | Sets the title.                                                                                                                                                  |
| **String**      | getTitle()                                                                        | Returns the Title.                                                                                                                                               |
| **void**        | unpop( )                                                                          | Unpop the MaterialWindow.                                                                                                                                        |
| **void**        | popup( )                                                                          | Popup the MaterialWindow.                                                                                                                                        |

### **References**

* See also our [quick video](https://www.youtube.com/watch?v=NN4qTuvO-tE) tutorial of how a material window
* See the [Label Java Docs ](https://rs.totalcross.com/doc/totalcross/ui/Label.html)for more information.


# MessageBox

### Overview

MessageBox is a popup element that shows a title, a text and one or more buttons.

<div align="left"><img src="/files/-Laa2H0no6TldckxVS6y" alt=""></div>

### Source Code

{% code title="MessageBoxSample.java" %}

```java
anybutton.addPressListener(new PressListener() {
    @Override
    public void controlPressed(ControlEvent e) {
        mb = new MessageBox("Did you know?", someMessage, new String[]{"Nice!"});
        mb.setRect(CENTER, CENTER, SCREENSIZE + 50, SCREENSIZE + 30);
        mb.setBackForeColors(Colors.P_300, Colors.ON_P_300);
        mb.popup();
    }
});
```

{% endcode %}

{% hint style="info" %}
Because it is an extensive example, we chose to exemplify the essential: how to use a **`MessageBox`**. To see the complete example, [click here](https://github.com/TotalCross/TCSample/blob/master/src/main/java/totalcross/sample/components/ui/MessageBoxSample.java).
{% endhint %}

### Attributes

| Type                | Name       | Description                         |
| ------------------- | ---------- | ----------------------------------- |
| **PushButtonGroup** | btns       | The messagebox button group         |
| **boolean**         | yPosition  | Messagebox vertical position        |
| **int\[ ]**         | buttonKeys | A int array that maps the button id |

### Methods

| Type            | Name                                                                                                                       | Description                                                                                                                                                                                      |
| --------------- | -------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
| **Constructor** | MessageBox(String title, String msg)                                                                                       | Constructs a message box with the text and one "Ok" button                                                                                                                                       |
| **Constructor** | MessageBox(String title, String text, String\[] buttonCaptions):                                                           | Constructs a message box with the text and the specified button captions                                                                                                                         |
| **Constructor** | MessageBox(String title, String text, String\[] buttonCaptions, boolean allSameWidth)                                      | Constructs a message box with the text and the specified button captions; The boolean specify if the buttons will have the same width                                                            |
| **Constructor** | MessageBox(String title, String text, String\[] buttonCaptions, boolean allSameWidth, int gap, int insideGap)              | Constructs a message box with the text and the specified button captions; The boolean specify if the buttons will have the same width; The ints specify the external and internal gaps           |
| **Constructor** | MessageBox(String title, String text, String\[] buttonCaptions, int gap, int insideGap)                                    | Constructs a message box with the text and the specified button captions; The ints specify the external and internal gaps                                                                        |
| **Constructor** | MessageBox(Image image, String title, String text, String\[] buttonCaptions, int gap, int insideGap)                       | Constructs a message box with the given text, button captions and image; The ints specify the external and internal gaps                                                                         |
| **Constructor** | MessageBox(Image image, String title, String text, String\[] buttonCaptions, boolean allSameWidth, int gap, int insideGap) | Constructs a message box with the given text, button captions and image; The boolean specify if the buttons will have the same width; The ints specify the external and internal gaps            |
| **Constructor** | Builder( )                                                                                                                 | Instances the MessageBox Builder. You can use it to make your MessageBox easily.                                                                                                                 |
| **Builder**     | setTitle(String title)                                                                                                     | Sets the MessageBox title.                                                                                                                                                                       |
| **Builder**     | setBaseContainer(Container baseContainer)                                                                                  | This is the content that will be placed between the title and the buttons. You can put anything here. After you set this, the message will not appear since you're putting a Container above it. |
| **Builder**     | setBaseContainerInsets(int left, int right, int top, int bottom)                                                           | Sets the insets of the Container (The container that will be your content).                                                                                                                      |
| **Builder**     | setImage(Image image)                                                                                                      | Sets the image that is displayed on the top of the MessageBox.                                                                                                                                   |
| **Builder**     | setMessageBoxInsets(int left, int right, int top, int bottom)                                                              | Sets the insets of the MessageBox.                                                                                                                                                               |
| **Builder**     | setButtons(String\[] buttonCaptions)                                                                                       | Sets the buttons that will appear on the MessageBox.                                                                                                                                             |
| **Builder**     | setButtonsMargin(int margin)                                                                                               | Sets the margins of the buttons.                                                                                                                                                                 |
| **Builder**     | setTitleContGap(int gap)                                                                                                   | Sets the gap between the title and the Container (MessageBox's content).                                                                                                                         |
| **Builder**     | setContButtonGap(int gap)                                                                                                  | Sets the gap between the Container (MessageBox's content) and the buttons.                                                                                                                       |
| **int**         | getPressedButtonIndex( )                                                                                                   | Returns the pressed button index                                                                                                                                                                 |
| **void**        | setDelayToShowButton(int ms)                                                                                               | Sets the show button delay                                                                                                                                                                       |
| **void**        | setIcon(Image icon)                                                                                                        | Set a icon in the title aligned at left                                                                                                                                                          |
| **void**        | setText(String text)                                                                                                       | Set a text after the popup of the messagebox                                                                                                                                                     |
| **void**        | setUnpopDelay(int unpopDelay)                                                                                              | Set a delay to the unpop animation                                                                                                                                                               |

### **References**

* See also the [quick video tutorial](https://www.youtube.com/watch?v=KJZyy9n5WZw) on how to create a MessageBox.&#x20;
* See the [JavaDocs](https://rs.totalcross.com/doc/totalcross/ui/MessageBox.html) fore more information.


# Multi Edit

### Overview

A MultiEdit is a field used to show or alter text in various disposed line

<div align="left"><img src="/files/-LaaJUfmY7JYeolZkIR_" alt=""></div>

### Source Code

{% code title="MultiEditSample.java" %}

```java
import totalcross.sys.Settings;
import totalcross.ui.MainWindow;
import totalcross.ui.MultiEdit;

public class MultiEditSample extends MainWindow {
	public MultiEditSample() {
		setUIStyle(Settings.MATERIAL_UI);
		Settings.uiAdjustmentsBasedOnFontHeight = true;
	}

	public void initUI() {
		MultiEdit multiEdit = new MultiEdit();
		multiEdit.caption = "MultiEdit";
		add(multiEdit, LEFT + 100,CENTER, FILL - 100, DP + 48);
	}
}
```

{% endcode %}

### Attributes

| Type        | Name       | Description                                                         |
| ----------- | ---------- | ------------------------------------------------------------------- |
| **boolean** | autoSelect | When true, the text will be selected when the MultiEdit is foccused |
| **String**  | caption    | The MultiEdit's placeholder text                                    |
| **boolean** | justify    | Justify the text when the MultiEdit is not editable                 |
| **boolean** | drawDots   | If true, a dotted line will be drawn on each line                   |

### Methods

| Type            | Name                                                        | Description                                                                                                                                                                                 |
| --------------- | ----------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| **Constructor** | MultEdit( )                                                 | Creates a MultiEdit for user input with the default size and spacing                                                                                                                        |
| **Constructor** | MultiEdit(int rowCount, int spaceBetweenLines)              | Creates a MultiEdit for user input with the passed row quantity and line spacing.                                                                                                           |
| **Constructor** | MultiEdit(String mask, int rowCount, int spaceBetweenLines) | Creates a MultiEdit for user input with the passed row quantity and line spacing, but with a mask.                                                                                          |
| **void**        | setEditable(boolean on)                                     | Will enable or disable the MultiEdit. Can be used as a way to make sure the user don't modify something that was already saved on server and can't be modified without proper authorization |
| **String**      | getText( )                                                  | Returns the text within the MultiEdit                                                                                                                                                       |
| **void**        | setMaxLength(int length)                                    | Is used to limit the characters number the user can digit on the text field                                                                                                                 |

### **References**

* See the [MultiEdit Java Docs ](https://rs.totalcross.com/doc/totalcross/ui/MultiEdit.html)for more information.


# Progress Bar

### Overview

It is a bar that can demonstrate the progress of a particular request or a loading of an event. You can have text that indicates the current status of the ProgressBar and can be used both horizontally and vertically.

### Source code

{% code title="ProgressBarSample" %}

```java
import totalcross.sys.Convert;
import totalcross.sys.Settings;
import totalcross.sys.Vm;
import totalcross.ui.Container;
import totalcross.ui.Control;
import totalcross.ui.MainWindow;
import totalcross.ui.ProgressBar;
import totalcross.ui.dialog.MessageBox;
import totalcross.ui.gfx.Color;
import totalcross.util.UnitsConverter;

public class ProgressBarSample extends MainWindow {
    ProgressBar  pbHYellow, pbVRed, pbVCyan, pbHRed, pbHPurple;
    int gap = UnitsConverter.toPixels(DP + 8);

    public ProgressBarSample() {
        setUIStyle(Settings.MATERIAL_UI);
    }

    @Override
    public void initUI() {
        try {
            super.initUI();

            Container sc = new Container();
            sc.setInsets(gap, gap, gap, gap);
            add(sc, LEFT, TOP, FILL, FILL);

            pbHPurple = new ProgressBar();
            pbHPurple.max = 50;
            pbHPurple.highlight = true;
            pbHPurple.suffix = " of " + pbHPurple.max;
            pbHPurple.textColor = 0xAAAA;
            pbHPurple.drawText = true;
            sc.add(pbHPurple, LEFT, TOP, FILL, PREFERRED);

            // endless ProgressBarSample
            pbHYellow = new ProgressBar();
            pbHYellow.max = width / 4; // max-min = width of the bar
            pbHYellow.setBackColor(Color.YELLOW);
            pbHYellow.setForeColor(Color.ORANGE);
            pbHYellow.prefix = "Loading, please wait...";
            pbHYellow.drawText = true;
            sc.add(pbHYellow, LEFT, AFTER + gap, FILL, PREFERRED);

            pbHRed = new ProgressBar();
            pbHRed.max = 50;
            pbHRed.setEndless();
            pbHRed.setBackForeColors(Color.DARK, Color.RED);
            sc.add(pbHRed, LEFT, AFTER + gap, FILL, FONTSIZE + 50);

            final int max = Settings.onJavaSE ? 2000 : 200;
            // vertical ones
            pbVCyan = new ProgressBar();
            pbVCyan.vertical = true;
            pbVCyan.max = max;
            pbVCyan.textColor = Color.BLUE;
            pbVCyan.setBackColor(Color.CYAN);
            pbVCyan.setForeColor(Color.GREEN);
            sc.add(pbVCyan, RIGHT, AFTER + gap, PREFERRED, FILL);

            pbVRed = new ProgressBar();
            pbVRed.vertical = true;
            pbVRed.max = 50;
            pbVRed.setBackForeColors(Color.RED, Color.DARK);
            sc.add(pbVRed, BEFORE - gap, SAME, FONTSIZE + 50, SAME);

            onSwapFinished();
        } catch (Exception ee) {
            MessageBox.showException(ee, true);
        }
    }

    @Override
    public void onSwapFinished() {
        final int ini = Vm.getTimeStamp();
        repaintNow();
        // runs the bench test
        int max = pbVCyan.max;
        for (int i = max; --i >= 0;) {
            int v = pbHPurple.getValue();
            v = (v + 1) % (pbHPurple.max + 1);
            Control.enableUpdateScreen = false; // since each setValue below updates the screen, we disable it to let it paint all at once at the end
            pbHPurple.setValue(v);
            pbVCyan.setValue(i);
            pbHYellow.setValue(5); // increment value
            pbHRed.setValue(v);
            Control.enableUpdateScreen = true;
            pbVRed.setValue(v);
            if (Settings.onJavaSE) {
                Vm.sleep(20);
            }
        }
    }
}
```

{% endcode %}

### Attributes

| Type        | Name      | Description                                                                                                        |
| ----------- | --------- | ------------------------------------------------------------------------------------------------------------------ |
| **int**     | max       | Progress Bar maximum value.                                                                                        |
| **int**     | value     | Current value of progress Bar.                                                                                     |
| **String**  | prefix    | It is the text that appears to the left of the value, remembering that the text output is prefix + value + sufix   |
| **String**  | suffix    | It is the text that appears to the right of the value, remembering that the text output is prefix + value + suffix |
| **boolean** | drawText  | It will indicate if the text will be displayed in progress bar or not, by default it comes as false.               |
| **boolean** | drawValue | It will indicate if the value will be displayed in the progress bar.                                               |

### Methods

| Type            | Name                                              | Description                                                                                                                                           |
| --------------- | ------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------- |
| **Constructor** | ProgressBar()                                     | Instances a ProgressBar with the minimum values 0 and maximum value 100.                                                                              |
| **Constructor** | ProgressBar(int min, int max)                     | Instances a ProgressBar with the values passed in the variables min and max.                                                                          |
| **Void**        | setEndless()                                      | Use in a horizontal ProgressBar to leave it without end.                                                                                              |
| **Void**        | setValue(int n)&#xD;                              | Updates the current progressbar value and draws the ProgressBar with the updated state.                                                               |
| **Void**        | setValue(int value, String prefix, String suffix) | <p>Updates the current value of progressBar and draws it again with the updated state and with texts before the value and after the value.</p><p></p> |

## References

* See the [Java Docs](https://rs.totalcross.com/doc/totalcross/ui/ProgressBar.html) for more information.
* You can check the example contained in the SDK, in tc.samples.api.ui ProgressBarSample.


# Progress Box

### Overview

Progress Box is a popup box with title, text, one or more buttons and a Spinner to demonstrate loading

<div align="left"><img src="/files/-LaaSn28nKbOkLfnBcd9" alt=""></div>

### Source Code

{% code title="ProgressBoxSample.java" %}

```java
import totalcross.sample.util.Colors;
import totalcross.ui.Button;
import totalcross.ui.ButtonMenu;
import totalcross.ui.Container;
import totalcross.ui.ProgressBar;
import totalcross.ui.Spinner;
import totalcross.ui.dialog.MessageBox;
import totalcross.ui.dialog.ProgressBox;
import totalcross.ui.gfx.Color;

public class ProgressBoxSample extends Container {
  private ButtonMenu menu;
  private ProgressBox pb;
  private int count;

  @Override
  public void initUI() {
    try {
      super.initUI();
      String[] items = {"ProgressBox (Android Spinner)", "ProgressBox (iOS Spinner)"};
      pb = new ProgressBox("Alert!", "null", items, true);
      

      Button bAndroid = new Button("Android Style");
      bAndroid.setBackForeColors(Colors.P_600, Colors.ON_P_600);
      bAndroid.addPressListener((e) -> {
          Spinner.spinnerType = Spinner.ANDROID;
          
          ProgressBoxSample.this.addTimer(1000);
          count = 4;
          
          pb = new ProgressBox("Alert!", "Please wait " + count + " seconds.");
          pb.setBackForeColors(Colors.P_700, Colors.ON_P_700);
          pb.popup();          
      });
      add(bAndroid, CENTER, CENTER - 60, 200 + DP, 40 + DP);
      
      Button bIOS = new Button("IOS Style");
      bIOS.setBackForeColors(Colors.P_600, Colors.ON_P_600);
      bIOS.addPressListener((e) -> {
          Spinner.spinnerType = Spinner.IPHONE;
          
          ProgressBoxSample.this.addTimer(1000);
          count = 4;
          
          pb = new ProgressBox("Alert!", "Please wait " + count + " seconds.");
          pb.setBackForeColors(Colors.P_700, Colors.ON_P_700);
          pb.popup();          
      });
      add(bIOS, CENTER, AFTER + 20, 200 + DP, 40 + DP);
      
      this.addTimerListener((e) -> {
    	  if(count >= 0) {
    		  pb.setText("Please wait " + count + " seconds.");
    		  count--;
    	  } else {
    		  pb.unpop();
    		  this.removeTimer(e);
    	  }
      });
      
    } catch (Exception ee) {
      MessageBox.showException(ee, true);
    }
  }
}
```

{% endcode %}

### Methods

| Type            | Name                                                                                                            | Description                                                                                                                                                                           |
| --------------- | --------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| **Constructor** | ProgressBox(String title, String msg)                                                                           | Creates a ProgressBox with text and an Ok Button                                                                                                                                      |
| **Constructor** | ProgressBox(String title, String text, String\[ ] buttonCaptions)                                               | Creates a ProgressBox with text and the specified Button                                                                                                                              |
| **Constructor** | ProgressBox(String title, String text, String\[ ] buttonCaptions, boolean allSameWidth)                         | Creates a ProgressBox with text and the specified Buttons. The boolean sets the buttons to have the same width                                                                        |
| **Constructor** | ProgressBox(String title, String text, String\[ ] buttonCaptions, boolean allSameWidth, int gap, int insideGap) | Creates a ProgressBox with text and the specified Buttons. The boolean sets the buttons to have the same width. The integers specify the external and internal spacing, respectively. |
| **Constructor** | ProgressBox(String title, String text, String\[ ] buttonCaptions, int gap, int insideGap)                       | Creates a ProgressBox with text and the specified Buttons. The integers specify the external and internal spacing, respectively                                                       |
| **void**        | onPopup( )                                                                                                      | Method called immediately before showing the ProgressBox                                                                                                                              |

### **References**

* See also our [quick tutorial video](https://www.youtube.com/watch?v=pSSNNXl6_98) showing how to create a Progress Box.
* See the [JavaDocs](https://rs.totalcross.com/doc/index.html) for more informations.


# Radio

### Overview

A `Radio` button is a button that can be either checked or unchecked. A user can tap the button to check or uncheck it. It can also be checked from the template using the checked property \
\
Use an element with a RadioGroupController attribute to group a set of radio button. When radio buttons are inside a RadioGroupController, just one radio in the group can be checked at any time. If a radio button is not placed in a group, they will all have the ability to be checked at the same time

<div align="left"><img src="/files/-LaaQZKLzPE9gMt-3bqx" alt=""></div>

{% hint style="info" %}
To see the complete sample, go to [github](https://github.com/TotalCross/RadioSample)
{% endhint %}

### Source Code

{% code title="RadioSample.java" %}

```java
import totalcross.sys.Settings;
import totalcross.ui.Bar;
import totalcross.ui.Check;
import totalcross.ui.Label;
import totalcross.ui.MainWindow;
import totalcross.ui.Radio;
import totalcross.ui.RadioGroupController;
import totalcross.ui.ScrollContainer;
import totalcross.ui.event.ControlEvent;
import totalcross.ui.event.PressListener;
import totalcross.ui.font.Font;
import totalcross.ui.gfx.Color;

public class RadioButton extends MainWindow{
	
	public RadioButton(){
		super("", BORDER_NONE);
		setUIStyle(Settings.Material);
		Settings.uiAdjustmentsBasedOnFontHeight = true;
		setBackForeColors(Color.WHITE, Color.BLACK);
		
		Bar h1 = new Bar("  RADIO");
		h1.canSelectTitle = false;
		h1.setFont(Font.getFont("Lato Bold", false, h1.getFont().size+3));
		h1.setBackForeColors(0XF8F8F8,Color.BLACK);		
		add(h1, LEFT,TOP,FILL,PREFERRED-50);
		
	}
	
	public void initUI(){
		ScrollContainer sc = new ScrollContainer(false, true);
	    add(sc,LEFT,AFTER,FILL,FILL);
	    
	    RadioGroupController radioGroup = new RadioGroupController();

	    Radio pyton = new Radio("Pyton", radioGroup);
	    pyton.setChecked(true);
	    sc.add(pyton, LEFT+100, AFTER+100 ,PREFERRED+100,PREFERRED+25);
	    
	    Radio java = new Radio("Java", radioGroup);
	    sc.add(java, LEFT+100, AFTER+50 ,PREFERRED+100,PREFERRED+25);

	    Radio ruby = new Radio("Ruby", radioGroup);
	    sc.add(ruby, LEFT+100, AFTER+50 ,PREFERRED+100,PREFERRED+25);
	    
	    Radio php = new Radio("PHP", radioGroup);
	    sc.add(php, LEFT+100, AFTER+50 ,PREFERRED+100,PREFERRED+25);

	    Label autolock = new Label("Auto-Lock");
	    autolock.setFont(Font.getFont("Lato Regular", false, autolock.getFont().size+3));
	    sc.add(autolock, LEFT+100, AFTER+100, FILL, PREFERRED+25);
	    
	    final Radio enable = new Radio("Enable: ''Never'' ");
	    enable.setChecked(true);
	    enable.setFont(Font.getFont("Lato Regular", false, Font.NORMAL_SIZE-2));
	    sc.add(enable, LEFT+123, AFTER+100 ,PREFERRED+100,PREFERRED+25);
	    
	    RadioGroupController radioGroup2 = new RadioGroupController();
	    
	    Radio rd1 = new Radio("1 Hour", radioGroup2);
	    rd1.setChecked(true);
	    sc.add(rd1, LEFT+100, AFTER+100 ,PREFERRED+100,PREFERRED+25);
	    
	    Radio rd2 = new Radio("2 Hours", radioGroup2);
	    sc.add(rd2, LEFT+100, AFTER+50 ,PREFERRED+100,PREFERRED+25);
	    
	    Radio rd3 = new Radio("3 Hours", radioGroup2);
	    sc.add(rd3, LEFT+100, AFTER+50 ,PREFERRED+100,PREFERRED+25);
	    
	    final Radio never = new Radio("Never", radioGroup2);
	    sc.add(never, LEFT+100, AFTER+50 ,PREFERRED+100,PREFERRED+25);
	    
	    enable.addPressListener(new PressListener(){
	    	public void controlPressed(ControlEvent e){
	    		boolean b = enable.isChecked();
	    		never.setEnabled(b);	
	        }
	    });
	    
	    Label properties = new Label("Properties");
	    properties.setFont(Font.getFont("Lato Regular", false, properties.getFont().size+3));
	    sc.add(properties, LEFT+100, AFTER+100, FILL, PREFERRED+25);
	    
	    Radio simple = new Radio("Simple Radio");
	    simple.setChecked(true);
	    sc.add(simple, LEFT+100, AFTER+100 ,PREFERRED+100,PREFERRED+25);
	    
	    Radio bcolor = new Radio("Background Color");
	    bcolor.setBackColor(Color.YELLOW);
	    bcolor.textColor = Color.BLUE;
	    bcolor.checkColor = uiMaterial ? Color.BLACK : Color.YELLOW;
	    sc.add(bcolor, LEFT+100, AFTER+50 ,PREFERRED+100,PREFERRED+25);
	    
	    Radio fcolor = new Radio("Foreground Color");
	    fcolor.setForeColor(Color.darker(Color.GREEN));
	    fcolor.checkColor = Color.GREEN;
	    sc.add(fcolor, LEFT+100, AFTER+50 ,PREFERRED+100,PREFERRED+25);
	}
}
```

{% endcode %}

### Attributes

| Type        | Name        | Description                                                                             |
| ----------- | ----------- | --------------------------------------------------------------------------------------- |
| **int**     | checkColor  | Set to the color of the check, if you want to make it different of the foreground color |
| **boolean** | leftJustify | Set to true to left justify this control if the width is above the preferred one        |
| **int**     | checkColor  | Sets the text color of the check                                                        |

### Métodos

| Tipo                     | Nome                                                | Descrição                                                                              |
| ------------------------ | --------------------------------------------------- | -------------------------------------------------------------------------------------- |
| **Constructor**          | Radio(String Text)                                  | Creates a radio control displaying the given text                                      |
| **Constructor**          | Radio(String text, RadioGroupController radioGroup) | Creates a radio control with the given text attached to the given RadioGroupController |
| **RadioGroupController** | getRadioGroup( )                                    | Returns the RadioGroupController that this radio belongs to, or null if none           |
| **String**               | getText( )                                          | Gets the text displayed in the radio                                                   |
| **boolean**              | isChecked( )                                        | Returns the checked state of the control                                               |
| **void**                 | setChecked(boolean checked)                         | Sets the checked state of the control                                                  |
| **void**                 | setChecked(boolean checked, boolean sendPress)      | Sets the checked state of the control, and send the press event if desired             |
| **void**                 | setText( )                                          | Sets the text                                                                          |

### **References**

* See also our [quick tutorial video](https://www.youtube.com/watch?v=7kFNoUWJ1YU) showing how to use Radios.&#x20;
* See the [JavaDocs](https://rs.totalcross.com/doc/totalcross/ui/Radio.html) for more information.


# Radio Group

### Overview

A radio group is a group of [Radios](https://totalcross.gitbook.io/playbook/ui-ux-api/radio) (**`RadioButton`**). It allows a user to select at most one radio from a set. Checking one RadioButton that belongs to a radio group unchecks any previous checked radio button within the same group.

<div align="left"><img src="/files/-LaaQZKLzPE9gMt-3bqx" alt=""></div>

### Source Code

{% code title="RadioGroupControllerSample.java" %}

```java
  // Creating a RadioGroup
RadioGroupController radioGroup = new RadioGroupController();
  // Assigning RadioButtons to the RadioGroup
Radio radio = new Radio("RadioButton", radioGroup);
add(radio, LEFT+100, AFTER+100 ,PREFERRED+100,PREFERRED+25);
```

{% endcode %}

{% hint style="info" %}
To see the complete example [click here](https://github.com/TotalCross/RadioSample/blob/master/src/main/java/radioButton/RadioButton.java).
{% endhint %}

### Attributes

| Type        | Name            | Description                                                            |
| ----------- | --------------- | ---------------------------------------------------------------------- |
| **boolean** | sendPressOnLast | Set to false to disable sending PRESSED events to the previous control |

### Methods

| Type            | Name                                                  | Description                                                                                                    |
| --------------- | ----------------------------------------------------- | -------------------------------------------------------------------------------------------------------------- |
| **Constructor** | RadioGroupController( )                               | Instance a empty RadioGroupController                                                                          |
| **int**         | add(Radio newMember )                                 | Adds a new Radio to the list of Radios this controller handles                                                 |
| **Radio**       | getRadio(int idx)                                     | Returns the Radio at the given index                                                                           |
| **int**         | getSelectedIndex( )                                   | Returns the currently selected index (in the order that the Radios were added to the container), or -1 if none |
| **Radio**       | getSelectedItem( )                                    | Returns the currently selected Radio, or null if none                                                          |
| **int**         | getSize( )                                            | Returns the number of Radio's                                                                                  |
| **void**        | remove(Radio oldMember)                               | Removes the given Radio from the list of Radios this controller handles                                        |
| **void**        | setSelectedIndex(int i)                               | Selects the given radio and deselects the other one                                                            |
| **void**        | setSelectedItem(String text)                          | Selects a radio whose text matches the given caption                                                           |
| **void**        | setSelectedItem(String text, boolean caseInsensitive) | Selects a radio whose text starts with the given caption                                                       |

### **References**

* See the [JavaDocs](https://rs.totalcross.com/doc/totalcross/ui/RadioGroupController.html) for more information


# Scroll Container

## Overview

The Container scroll is a container that has side scroll, horizontal scroll or no scroll.

### How to use

```java
public class ScrollContainerSample extends MainWindow {

    public ScrollContainerSample(){
        setUIStyle(Settings.Material);
    }

    @Override
        public void initUI() {
            super.initUI();
            ScrollContainer sc = new ScrollContainer(false, true);
            int gap = UnitsConverter.toPixels(DP + 16);
            sc.setInsets(gap, gap, gap, gap);
            add(sc, LEFT, TOP, FILL, FILL);

            Button b;
            ScrollContainer sc1, sc2, sc3;
            // a ScrollContainer with both ScrollBars
            sc.add(new Label("Vertical and horizontal:"), LEFT, TOP);
            sc.add(sc1 = new ScrollContainer());
            sc1.setBorderStyle(BORDER_ROUNDED);
            sc1.setInsets(3, 3, 3, 3);
            sc1.setRect(LEFT, AFTER, FILL, SCREENSIZE + 30);
            int xx = new Label("Name99").getPreferredWidth() + 2; // edit's alignment
            for (int i = 0; i < 50; i++) {
                sc1.add(new Label("Name" + i), LEFT, AFTER + 10);
                sc1.add(new Edit(), xx, SAME, SCREENSIZE + 90, PREFERRED);
                if (i % 3 == 0) {
                    sc1.add(new Button("Go"), AFTER + 2, SAME, PREFERRED, SAME);
                }
            }

            // a ScrollContainer with vertical ScrollBar disabled
            sc.add(new Label("Horizontal-only:"), LEFT, AFTER + gap);
            sc.add(sc2 = new ScrollContainer(true, false));
            sc2.setBorderStyle(BORDER_ROUNDED);
            sc2.setInsets(3, 3, 3, 3);
            int lines = Settings.screenHeight > 320 ? 4 : 3;
            sc2.setRect(LEFT, AFTER, FILL, lines * (fmH + Edit.prefH) + fmH / 2);
            for (int i = 0; i < lines; i++) {
                sc2.add(new Label("Name" + i), LEFT, AFTER);
                sc2.add(new Edit(""), xx, SAME, PARENTSIZE + 200, PREFERRED); // fit
                sc2.add(new Button("Go"), AFTER, SAME, PREFERRED, SAME);
            }

            // a ScrollContainer with horizontal ScrollBar disabled
            sc.add(new Label("Vertical-only:"), LEFT, AFTER + gap);
            sc.add(sc3 = new ScrollContainer(false, true));
            sc3.setBorderStyle(BORDER_ROUNDED);
            sc3.setInsets(3, 3, 3, 3);
            sc3.setRect(LEFT, AFTER, FILL, SCREENSIZE + 30);
            for (int i = 0; i < 50; i++) {
                sc3.add(new Label("Name" + i), LEFT, AFTER);
                sc3.add(b = new Button("Go"), RIGHT, SAME, PREFERRED, SAME);
                sc3.add(new Edit(""), xx, SAME, FIT - 2, PREFERRED, b); // fit
            }
        }
}
```

## References

* To know more details read its [JavaDocs](https://rs.totalcross.com/doc/totalcross/ui/ScrollContainer.html).

[<br>](https://app.gitbook.com/@totalcross/s/playbook/~/drafts/-LfzE7W6V32fHcj-QL-S/primary/apis/visao-geral-da-api)


# Side Menu

## Overview

**The SideMenu component is a navigation drawer that slides on the side of the current view. By default, slide from the left, but the side can be replaced. The sideMenu is customized through containers and specifications that allow you to set the SideMenu object or through the SideMenuContainer class.**

**The sideMenu, as an important part of the user interface, have their own standards. Therefore it is recommended to review the** [**Material Design**](http://www.totalcross.com/blog/material-o-layout-da-google/) **for more information and to enjoy the component better. To learn how to design notifications and their interactions, read what MaterialDesing talks about** [**Menus**](https://material.io/guidelines/components/menus.html)**.**

![](/files/-Lh5gbbk4wp1PBQAGGiY)

## **Creating SideMenu**

**First, you create the `SideMenuContainer`object and inside the `initUI()` you instantiate the objects corresponding to the items, through the `SideMenuContainer.Item` and there you pass the characteristics you want, such as caption, icon, presenter.**

**After that, you instantiate your `SideMenuContainer`object and point to the `SideMenuContainer.item` that you created earlier.**

**And then just customize the header of your Side** **Menu through `topMenu.header.`**

**Finally just pass the other information you want on your `sideMenuContainer` object, such as font color, bar size and so on.**<br>

### **Content Needed to Create a SideMenu**

* **`sideMenuContainer`**
* **`sideMenuContainer.Item`**
  * **Capition**
  * **Image or IconType**
  * **Presenter**
* **`TopMenu.Header`**
* **`Icon _Menu.`**

### **Optional SideMenu Settings and Content**

**Inside the sideMenuContainer.Item you can still have:**

* **Caption**
* **Image or IconType (advise using MaterialIcon)**
* **Color**
* **Boolean showTitle**
* **Presenter**

**And you can even specify directly in the sideMenuContainer.topMenu:**

* **`.drawSeparators = boolean` - To place or not the lines separating the items**
* **`.itemHeightFactor = int` - To say the item's size.**

## **Usage**

{% code title="SideMenuSample" %}

```java
public void initUI(){
		SideMenuContainer.Item home = new SideMenuContainer.Item("Home", MaterialIcons._HOME, 0x4A90E2, ()-> {return new Home();});
		SideMenuContainer.Item sample = new SideMenuContainer.Item("Home", MaterialIcons._THUMB_UP, 0x4A90E2, ()-> {return new Sample();});
		SideMenuContainer sideMenu = new SideMenuContainer(null, home, sample);
		
		sideMenu.topMenu.header = new Container(){
			public void initUI(){
				setBackColor(0xaa443b);
				
				Label title = new Label("SideMenu", CENTER, Color.WHITE, false);
				title.setFont(Font.getFont("Lato Bold", false, this.getFont().size+5));
				title.setForeColor(Color.WHITE);
				add(title, LEFT+45, BOTTOM-45, PARENTSIZE+40, DP+56);
			}
		};
		
		sideMenu.setBarFont(Font.getFont(Font.getDefaultFontSize()+2));
		sideMenu.setBackColor(0x4A90E2);
		sideMenu.setForeColor(Color.WHITE);
		sideMenu.setItemForeColor(Color.BLACK);
		sideMenu.topMenu.drawSeparators = false;
		sideMenu.topMenu.itemHeightFactor = 3;
		
		Icon icon = new Icon(MaterialIcons._MENU);
		icon.setBackColor(Color.WHITE);
		add(icon, CENTER, TOP);
		add(sideMenu, LEFT, TOP, PARENTSIZE, PARENTSIZE);
	}
```

{% endcode %}

## **References**

* **To see the complete example, just click** [**here**](https://github.com/TotalCross/SideMenuSample)


# Slider

### Overview

A Slider is a component that allows the user to slide a bar to pick a value between a range

<div align="left"><img src="https://totalcross.com/documentation/img/samples/slider-sample.gif" alt=""></div>

{% code title="SliderSample.java" %}

```java
import totalcross.sys.Settings;
import totalcross.ui.Container;
import totalcross.ui.Label;
import totalcross.ui.ScrollBar;
import totalcross.ui.Slider;
import totalcross.ui.dialog.MessageBox;
import totalcross.ui.event.ControlEvent;
import totalcross.ui.event.Event;
import totalcross.ui.font.Font;
import totalcross.ui.gfx.Color;
import totalcross.ui.ScrollContainer;


public class SliderSample extends ScrollContainer {
  private Label l;
  private ScrollContainer sc;
  
  @Override
  public void initUI() {
    try {
      super.initUI();
      setScrollBars(false, true);
      
      add(l = new Label("", CENTER), LEFT, TOP);

      Slider sl;
      sl = new Slider(ScrollBar.HORIZONTAL);
      sl.setFont(Font.getFont(false, Font.NORMAL_SIZE));
      sl.appId = 1;
      sl.setLiveScrolling(true);
      sl.setBackColor(Color.getRGB(158, 197, 244));
      sl.sliderColor = Color.getRGB(12, 98, 200);
      sl.setValue(10);
      add(sl,CENTER, TOP + fmH * 2 + 150, (Settings.screenWidth - ((Settings.screenWidth)/10)*2), PREFERRED);
      
      
      
      sl = new Slider(ScrollBar.HORIZONTAL);
      sl.setFont(Font.getFont(false, Font.NORMAL_SIZE / 2 * 3));
      sl.appId = 2;
      sl.setUnitIncrement(5);
      sl.drawTicks = false;
      sl.setBackColor(Color.getRGB(255, 234, 157));
      sl.sliderColor = Color.getRGB(255, 199, 0);
      
      sl.setValue(30);
      add(sl, CENTER, AFTER + fmH + 100, (Settings.screenWidth - ((Settings.screenWidth)/10)*2), PREFERRED);

      sl = new Slider(ScrollBar.HORIZONTAL);
      sl.setFont(Font.getFont(false, Font.NORMAL_SIZE / 2 * 4));
      sl.appId = 3;
      sl.invertDirection = true;
      sl.setBackColor(Color.getRGB(255, 192, 157));
      sl.sliderColor = Color.getRGB(255, 92, 0);
      sl.setValue(50);
      add(sl, CENTER, AFTER + fmH + 50, (Settings.screenWidth - ((Settings.screenWidth)/10)*2), PREFERRED);

      sl = new Slider(ScrollBar.VERTICAL);
      sl.setFont(Font.getFont(false, Font.NORMAL_SIZE));
      sl.appId = 4;
      sl.setLiveScrolling(true);
      sl.setBackColor(Color.getRGB(149, 243, 230));
      sl.sliderColor = Color.getRGB(0, 195, 168);
      sl.setValue(70);
      add(sl, BEFORE + 200 , AFTER + fmH + 200, PREFERRED, Settings.screenHeight/3);

      sl = new Slider(ScrollBar.VERTICAL);
      sl.setFont(Font.getFont(false, Font.NORMAL_SIZE / 2 * 3));
      sl.appId = 5;
      sl.setLiveScrolling(true);
      sl.setBackColor(Color.getRGB(255, 220, 157));
      sl.sliderColor = Color.getRGB(255, 164, 0);
      sl.setValue(90);
      add(sl, CENTER , SAME, PREFERRED, Settings.screenHeight/3);

      sl = new Slider(ScrollBar.VERTICAL);
      sl.setFont(Font.getFont(false, Font.NORMAL_SIZE / 2 * 4));
      sl.appId = 6;
      sl.invertDirection = true;
      sl.setBackColor(Color.getRGB(254, 156, 165));
      sl.sliderColor = Color.getRGB(255, 0, 24);
      sl.setValue(50);
      add(sl,AFTER + 200, SAME, PREFERRED, Settings.screenHeight/3);
    } catch (Exception ee) {
      MessageBox.showException(ee, true);
    }
  }

  @Override
  public void onEvent(Event e) {
    if (e.type == ControlEvent.PRESSED && e.target instanceof Slider) {
      Slider s = (Slider) e.target;
    }
  }
}
```

{% endcode %}

### Attributes

| Type        | Name            | Description                                                                                                                                                                                                                                                                                                            |
| ----------- | --------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| **boolean** | drawFilledArea  | Setting to false does not draw the filled line\* of the Slider                                                                                                                                                                                                                                                         |
| **boolean** | drawTicks       | Defining as true, ticks will be drawn along the Slider to indicate all the possible points where the Slider may be. By default, the number of ticks to be drawn are the same as the maximum slider value, (SeeMethods bellow), but this value can be modified by setting a different value for setUnitIncrement(int i) |
| **boolean** | invertDirection | Setting to True causes the filled area of the Slider to be the rightmost part of the scroll circle, which by default is the leftmost                                                                                                                                                                                   |
| **int**     | sliderColor     | Changing this attribute value colors the circle and the filled line\* of the Slider                                                                                                                                                                                                                                    |

### Methods

| Type            | Name                     | Description                                                                                                                                           |
| --------------- | ------------------------ | ----------------------------------------------------------------------------------------------------------------------------------------------------- |
| **Constructor** | Slider( )                | Cria um Slider **na posição horizontal** com o limite mínimo e máximo de 0 e 100, respectivamente                                                     |
| **Constructor** | Slider(byte orientation) | Cria um Slider **na posição desejada** com o limite mínimo e máximo de 0 e 100, respectivamente,                                                      |
| **void**        | setMinimum(int i)        | Sets the minimum value of the bar limit                                                                                                               |
| **void**        | setMaximum(int i)        | Sets the maximum value of the bar limit                                                                                                               |
| **void**        | setUnitIncrement(int i)  | Sets the value that will be incremented or decremented to the Slider while using a PenDrag event                                                      |
| **void**        | setValue(int i)          | Sets the starting value for the Slider to begin with. If this initial value is greater than the maximum value, then it will be limited to the maximum |

### **References**

See the [JavaDocs](https://rs.totalcross.com/doc/totalcross/ui/Slider.html) for more information


# Sliding Window

### **Overview**

Sliding Window is a fullscreen window that slides in and out of the screen during pop and unpop events. Use it to create transition effects between screens.

![](/files/-MFXIhvbiGTIMLMGkdeZ)

### Source Code

{% tabs %}
{% tab title="SlidingWindow class" %}

```java
package com.totalcross;

import totalcross.ui.Container;
import totalcross.ui.Presenter;
import totalcross.ui.SlidingWindow;

public class MySlidingWindow extends SlidingWindow {

    public MySlidingWindow(boolean delayInitUI, Presenter<Container> provider) {
        super(delayInitUI, provider);
    }

    public MySlidingWindow(Presenter<Container> provider, int animDir,
                                                          int totalTime){
        super(provider);
        this.animDir = animDir; // This can be LEFT or RIGHT, any other will
                                // be BOTTOM
        this.totalTime = totalTime; // Time, in milliseconds for the animation
    }
}
```

{% endtab %}

{% tab title="Calling the SlidingWindow" %}

```java
MySlidingWindow slidingWindow = new MySlidingWindow(new Presenter<Container>(){
            
		 @Override
		 public Container getView() {
				return new Container() {
          public void initUI() {
            ImageControl i;
            try {
                i = new ImageControl(new Image("images/logoV.png"));
                i.scaleToFit = true;
                i.centerImage = true;
                add(i, CENTER, CENTER, 100 + DP, 100 + DP);
            } catch (IOException e) {
                e.printStackTrace();
            } catch (ImageException e) {
                e.printStackTrace();
            }
          };
        };
	   }
}, RIGHT, 500);
slidingWindow.popup();
```

{% endtab %}
{% endtabs %}

{% hint style="info" %}
Because it is a more complex example, we only show the specific Sliding Window example code, if you want to see the whole code of the image interface construction [click here](https://github.com/TotalCross/TCSample/blob/master/src/main/java/totalcross/sample/components/Home.java).
{% endhint %}

### Methods

| Type            | Name                                                               | Description                                                                                                                                                                                                                                                                                                                                                                       |
| --------------- | ------------------------------------------------------------------ | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| **Constructor** | SlidingWindow(Presenter\<Container> provider)                      | Creates a SlidingWindow with the specified provider. Use the provider class to implement your view code.                                                                                                                                                                                                                                                                          |
| **Constructor** | SlidingWindow(Presenter\<Container> provider, boolean delayInitUI) | Creates a SlidingWindow with the specified provider and if it should delay the InitUI execution. Use the delayed InitUI if your screen takes a significant amount of time to load (e.g., it fetches data from a server) and the non-delayed InitUI if it is fast enough to be loaded prior to the animation. If the delayed option is used, the screen will popup with a spinner. |
| **void**        | unpop( )                                                           | Unpops the SlidingWindow, hiding it.                                                                                                                                                                                                                                                                                                                                              |
| **void**        | popup( )                                                           | Popups the SlidingWindow, showing it.                                                                                                                                                                                                                                                                                                                                             |


# Spin List

### Overview

Spin list is a control that has two arrows (up and down) to navigate between the information contained in the control, it is possible to navigate by clicking or holding the arrows or navigating the keyboard arrows.

### Source Code

{% code title="SpinList Sample" %}

```java
import totalcross.sys.InvalidNumberException;
import totalcross.sys.Settings;
import totalcross.ui.Container;
import totalcross.ui.MainWindow;
import totalcross.ui.SpinList;
import totalcross.ui.gfx.Color;
import totalcross.util.UnitsConverter;

public class SpinListSample extends MainWindow {

    int gap = UnitsConverter.toPixels(DP + 8);

    public SpinListSample(){
        setUIStyle(Settings.MATERIAL_UI);
    }

    @Override
    public void initUI() {
        try {
            SpinList sl = new SpinList(new String[]{"Blue", "Orange","Yelow", "Red"});
            sl.allowsNoneSelected = true;
            add(sl, LEFT + gap, TOP + gap, FILL, PREFERRED);

            Container paintContainer = new Container();
            add(paintContainer, SAME, AFTER + gap, FILL - gap, FILL - gap);


            sl.addPressListener(e -> {
                switch (sl.getSelectedIndex()){
                    case -1:
                        paintContainer.setBackColor(Color.WHITE);
                        break;
                    case 0:
                        paintContainer.setBackColor(Color.BLUE);
                        break;
                    case 1:
                        paintContainer.setBackColor(Color.ORANGE);
                        break;
                    case 2:
                        paintContainer.setBackColor(Color.YELLOW);
                        break;
                    case 3:
                        paintContainer.setBackColor(Color.RED);
                        break;
                }
            });

        } catch (InvalidNumberException e) {
            e.printStackTrace();
        }
    }
}
```

{% endcode %}

###

### Attributes

| Type        | Name               | Description                                                                                                                                                            |
| ----------- | ------------------ | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| **boolean** | isVertical         | Set to true if there are only numbers in the SpinList and you want to open a NumericBox                                                                                |
| **boolean** | useNumericBox      | Set to true if there are only numbers in the SpinList and you want to open a NumericBox                                                                                |
| **boolean** | useCalculatorBox   | Set to false to disallow the wrap around that happens when the user is at the first or last items.                                                                     |
| **boolean** | wrapAround         | By default, equals the choices' length. You can define its length and then create a single array shared  by a set of SpinLists with different lengths on each SpinList |
| **boolean** | allowsNoneSelected | Allows -1 as selected index                                                                                                                                            |

### Methods

| Type            | Name                                            | Description                                                                                            |
| --------------- | ----------------------------------------------- | ------------------------------------------------------------------------------------------------------ |
| **Constructor** | SpinList(String\[] choices)                     | Constructs a vertical SpinList with the given choices, selecting index 0 by default.                   |
| **Constructor** | SpinList(String\[] choices, boolean isVertical) | Constructs a SpinList with the given choices, selecting index 0 by default and can be vertical or not. |
| **int**         | getPreferredWidth()                             | Return the width.                                                                                      |
| **int**         | getPreferredHeight()                            | Return the Height.                                                                                     |
| **void**        | setChoices(String\[] choices)                   | Sets the choices to the given ones                                                                     |
| **void**        | replaceChoices(String\[] choices)               | Just replaces the choices array.                                                                       |
| **int**         | getSelectedIndex()                              | Returns the selected index.                                                                            |
| **String**      | getSelectedItem()                               | Returns the selected item.                                                                             |

## References

* See the [Java Docs](https://rs.totalcross.com/doc/totalcross/ui/SpinList.html) for more information.


# Spinner

### Overview

Spinner is a control that shows an image indicating that something is running in the background. It has two styles: **iPhone** and **Android**.

<div align="left"><img src="https://totalcross.com/documentation/img/samples/spinner-sample.gif" alt=""></div>

### Source Code

{% code title="SpinnerSample.java" %}

```java
  //Spinner inside the Bar
Bar bar = new Bar (“text text”);
add(bar, LEFT, TOP, FILL, PREFERRED);
bar.createSpinner(Color.WHITE);
bar.startSpinner;

  //Spinner inside the Loop
Spinner spinner = new Spinner(Spinner.IPHONE);
spinner.setForeColor(Color.WHITE);
add(spinner, CENTER, AFTER,, FONTSIZE + 200, FONTSIZE + 200);

while (Vm.getTimeStamp()  < (Vm.getTimeStamp() + 5000))
{
    spinner.update();
}

  //Spinner inside the ProgressBox
Spinner.spinnerType = Spinner.ANDROID;
ProgressBox pb = new ProgressBox("Alert!", “msg”, null);
pb.setBackColor(Color.getRGB(12, 98, 200));
pb.popupNonBlocking();
```

{% endcode %}

### Methods

| Type            | Name                 | Description                                                         |
| --------------- | -------------------- | ------------------------------------------------------------------- |
| **Constructor** | Spinner( )           | Creates a simple Spinner                                            |
| **Constructor** | Spinner(Image anim)  | Creates a spinner from an animated GIF                              |
| **Constructor** | Spinner(int type)    | Creates a spinner of the given type                                 |
| **boolean**     | isRunning( )         | Returns if the spin is running                                      |
| **void**        | setImage(Image anim) | Changes the gif image of this Spinner                               |
| **void**        | setType(int t)       | Changes the Spinner to one of the predefined types                  |
| **void**        | start( )             | Starts the spinning thread                                          |
| **void**        | stop( )              | Stops the spinning thread                                           |
| **void**        | update( )            | Updates the spinner; call this when using the spinner inside a loop |

### **References**

* See also our [quick tutorial video](https://www.youtube.com/watch?v=b19EB2gN80E) showing how to use Spinner.
* See the [JavaDocs](https://rs.totalcross.com/doc/totalcross/ui/Spinner.html) for more informatio&#x6E;**.**


# Switch

### Overview

Switch is a element that chooses between two proportions

{% code title="SwitchSample.java" %}

```java
 // Instance a simple switch
subtitles = new Switch();

 // Set the colors up
subtitles.colorBallOn = Color.getRGB(0,150,136);
subtitles.colorBarOn = Colors.P_700;
subtitles.colorBallOn = Color.getRGB(241,241,241);
subtitles.colorBarOff = Colors.P_200;

 // Positions the switch 
add(subtitles, RIGHT-hGap, SAME+lsfx.getHeight()/2, PREFERRED, PREFERRED);
```

{% endcode %}

{% hint style="info" %}
This sample code is only from the Switch, to see the complete sample, including the Slider, go to [github](https://github.com/TotalCross/TCSample/blob/master/src/main/java/totalcross/sample/components/ui/SliderSwitchSample.java)
{% endhint %}

### Attributes

| Type        | Name         | Description                                                     |
| ----------- | ------------ | --------------------------------------------------------------- |
| **boolean** | centerText   | Boolean that center the text instead of move from left to right |
| **int**     | colorBackOff | Background color for off switch                                 |
| **int**     | colorBackOn  | Background color for on switch                                  |
| **int**     | colorForeOff | Foreground color for off switch                                 |
| **int**     | colorForeOn  | Foreground color for on switch                                  |
| **String**  | textBackOff  | Background text for off switch                                  |
| **String**  | textBackOn   | Background text for on switch                                   |
| **String**  | textForeOff  | Foreground text for off switch                                  |
| **String**  | textForeOn   | Foreground text for on switch                                   |

### Methods

| Type            | Name                       | Description                       |
| --------------- | -------------------------- | --------------------------------- |
| **Constructor** | Switch( )                  | Creates a simple switch           |
| **int**         | getPreferredHeight( )      | Returns the switch minimum height |
| **int**         | getPreferredWidth( )       | Returns the switch minimum width  |
| **boolean**     | isOn( )                    | Return true if the switch is on   |
| **void**        | moveSwitch(boolean toLeft) | If true, move the switch to left  |
| **void**        | setOn(boolean b)           | If true, turn on the switch       |
| **void**        | setPos(int x, int y)       | Set the Switch´s x and y position |

### **References**

* See the [JavaDocs](https://rs.totalcross.com/doc/totalcross/ui/Switch.html) for more information.


# Tabbed Container

### Overview

Tabbed Container is a control that has tabs that can have text and / or images. It has an automatic scrool, that is, by clicking on a specific tab, the controler simulates the drag to the chosen tab.

### Source Code

```java
import totalcross.io.IOException;
import totalcross.sample.util.Colors;
import totalcross.sys.Settings;
import totalcross.ui.Container;
import totalcross.ui.Label;
import totalcross.ui.ScrollContainer;
import totalcross.ui.TabbedContainer;
import totalcross.ui.dialog.MessageBox;
import totalcross.ui.gfx.Color;
import totalcross.ui.image.Image;
import totalcross.ui.image.ImageException;

public class TabbedContainerSample extends ScrollContainer {
	private final int gap = (int)(Settings.screenDensity * 30);

	@Override
	public void initUI() {
		try {
			setBackForeColors(Colors.BACKGROUND, Colors.ON_BACKGROUND);

			CreateImageAndTextTabbedContainer();
			CreateTextOnlyTabbedContainer();
			CreateBulletsTabbedContainer();
		} catch (Exception ee) {
			MessageBox.showException(ee, true);
		}
	}

	private void CreateImageAndTextTabbedContainer() throws ImageException, IOException {
		String[] caps = { 
			"Social 1", 
			"Social 2", 
			"Social 3" 
		};
		Image[] icons = { 
			new Image("images/fb_icon_40.png"), 
			new Image("images/gmail_icon_40.png"),
			new Image("images/insta_icon_40.png") 
		};

		Label sampleTitle = new Label("This is a icon and text Tabbed Container", CENTER);
		sampleTitle.autoSplit = true;
		add(sampleTitle, LEFT + gap, TOP + gap, FILL - gap, PREFERRED);
		
		Container spacing = new Container();
		add(spacing, LEFT + gap*2, AFTER + gap/2, FILL - gap*2, (int) (Settings.screenHeight * 0.3));
		
		final TabbedContainer tc = new TabbedContainer(caps);
		tc.setBackColor(Color.DARK);
		tc.getContainer(0).setBackColor(Colors.P_300);
		tc.getContainer(1).setBackColor(Colors.P_400);
		tc.getContainer(2).setBackColor(Colors.P_500);
		tc.setIcons(icons);
		tc.pressedColor = Colors.P_800;
		tc.activeTabBackColor = Colors.P_800;
		tc.allSameWidth = true;
		tc.extraTabHeight = fmH * 2;
		spacing.add(tc, LEFT, TOP, FILL, PARENTSIZE);
		for(int i = 0; i < 3; i++)
			tc.getContainer(i).add(new Label("Container " + (i+1)), CENTER, CENTER);
	}

	private void CreateTextOnlyTabbedContainer() throws ImageException, IOException {
		String[] caps = new String[3];
		caps[0] = "Home";
		caps[1] = "Photos";
		caps[2] = "Profile";
		
		
		Label sampleTitle = new Label("This is a text only Tabbed Container", CENTER);
		sampleTitle.autoSplit = true;
		add(sampleTitle, LEFT + gap, AFTER + gap*2, FILL - gap, PREFERRED);
		
		Container spacing = new Container();
		add(spacing, LEFT + gap*2, AFTER + gap/2, FILL - gap*2, (int) (Settings.screenHeight * 0.3));
		
		final TabbedContainer tc = new TabbedContainer(caps);
		tc.setType(TabbedContainer.TABS_BOTTOM);
		tc.setBackColor(Color.DARK);
		tc.getContainer(0).setBackColor(Colors.P_300);
		tc.getContainer(1).setBackColor(Colors.P_400);
		tc.getContainer(2).setBackColor(Colors.P_500);
		tc.useOnTabTheContainerColor = true;
		tc.allSameWidth = true;
		tc.extraTabHeight = fmH / 2;
		spacing.add(tc, LEFT, TOP, FILL, PARENTSIZE);
		for(int i = 0; i < 3; i++)
			tc.getContainer(i).add(new Label("Container " + (i+1)), CENTER, CENTER);
	}

	private void CreateBulletsTabbedContainer() throws ImageException, IOException {
		Image[] images = new Image[3];
		Image empty = new Image("images/bullet_empty.png").getSmoothScaledInstance(fmH, fmH);
		Image filled = new Image("images/bullet_full.png").getSmoothScaledInstance(fmH, fmH);
		filled.applyColor2(Color.ORANGE);

		for (int i = images.length; --i >= 0;) {
			images[i] = empty;
		}
		
		Label sampleTitle = new Label("This is a image-only Tabbed Container", CENTER);
		sampleTitle.autoSplit = true;
		add(sampleTitle, LEFT + gap, AFTER + gap*2, FILL - gap, PREFERRED);
		
		Container spacing = new Container();
		add(spacing, LEFT + gap*2, AFTER + gap/2, FILL - gap*2, (int) (Settings.screenHeight * 0.3));

		final TabbedContainer tc = new TabbedContainer(images);
		tc.setActiveIcon(filled);
		tc.setType(TabbedContainer.TABS_BOTTOM);
		tc.setBackColor(Color.DARK);
		tc.getContainer(0).setBackColor(Colors.P_300);
		tc.getContainer(1).setBackColor(Colors.P_400);
		tc.getContainer(2).setBackColor(Colors.P_500);
		tc.allSameWidth = true;
		tc.extraTabHeight = fmH / 2;
		tc.setBorderStyle(Container.BORDER_NONE);
		tc.transparentBackground = true;
		spacing.add(tc, LEFT, TOP, FILL, PARENTSIZE);
		for(int i = 0; i < 3; i++)
			tc.getContainer(i).add(new Label("Container " + (i+1)), CENTER, CENTER);
	}
}
```

### Methods

| Tipo          | Nome                                                        | Descrição                                                                                   |
| ------------- | ----------------------------------------------------------- | ------------------------------------------------------------------------------------------- |
| **Construct** | TabbedContainer(String\[] strCaptions)                      | Uses a string array as capations for the tabs.                                              |
| **Construct** | TabbedContainer(Image\[] imgCaptions, int transparentColor) | Uses an image array to represent the flaps and set a color.                                 |
| **Construct** | TabbedContainer(Image\[] imgCaptions)                       | Uses an image array to represent the flaps                                                  |
| **Container** | getContainer(int i)                                         | Returns the Container for tab                                                               |
| **Void**      | setType(byte type)                                          | <p>Sets the position of the tabs.</p><p>You can use TABS\_TOP, TABS\_BOTTOM, TABS\_NONE</p> |

### References

* See a example on [github](https://github.com/TotalCross/TCSample/blob/master/src/main/java/totalcross/sample/components/ui/TabbedContainerSample.java) .
* See the [Java Docs](https://rs.totalcross.com/doc/totalcross/ui/Grid.html) for more information.


# Velocimeter

### Overview

The Velocimeter represents a velocimeter gauge. The background and pointer can be customized. The text, max and min values can be drawn or not. The pointer's color can be changed

<div align="left"><img src="https://totalcross.com/documentation/img/samples/velocimeter-sample.gif" alt=""></div>

{% code title="VelocimeterSample.java" %}

```java
  // Adds a timer
tt = addTimer(50);

  // Creates a simple Velocimeter
vel = new Velocimeter();
vel.value = -20;
vel.max = 40;
vel.pointerColor = Color.GREEN;
add(vel, CENTER, CENTER, PARENTSIZE + 50, PARENTSIZE + 50);

// Generates an event from the timer
@Override
public void onEvent(Event e)
{
	if (e.type == TimerEvent.TRIGGERED && tt.triggered)
	{
		vel.value++;
		if (vel.value > vel.max + 20)
		{
			vel.value = vel.min - 20;
		}
		repaint();
	}
}
```

{% endcode %}

{% hint style="info" %}
To view the full code, [click here](https://github.com/TotalCross/TCSample/blob/master/src/main/java/totalcross/sample/components/ui/VelocimeterSample.java).
{% endhint %}

### Attributes

| Type        | Name         | Description                                                            |
| ----------- | ------------ | ---------------------------------------------------------------------- |
| **boolean** | drawMax      | Set to false to don't draw the max value's text                        |
| **boolean** | drawMin      | Set to false to don't draw the min value's text                        |
| **boolean** | drawValue    | Set to false to don't draw the value's text.                           |
| **int**     | max          | The maximum value; defaults to 100.                                    |
| **int**     | maxAngle     | The maximum angle value; defaults to 270 degrees for the default gauge |
| **int**     | min          | The minimum value; defaults to 0                                       |
| **int**     | pointerColor | The pointer's color                                                    |
| **int**     | value        | The current value                                                      |
| **int**     | valueColor   | The value's color.                                                     |

### Methods

| Type            | Name                                                        | Description                                                         |
| --------------- | ----------------------------------------------------------- | ------------------------------------------------------------------- |
| **Constructor** | Velocimeter( )                                              | Constructs a velocimeter using the default gauge and pointer images |
| **Constructor** | Velocimeter(String gaugeImagePath, String pointerImagePath) | Constructs a velocimeter using the given images                     |

### **References**

See the [JavaDocs](https://rs.totalcross.com/doc/totalcross/ui/chart/Velocimeter.html) for more information.


# APIs


# API Overview

Short description about the Totalcross API

## **TotalCross Packages**

### totalcross.crypto

The classes used by TotalCross to work with encryption are:&#x20;

* **Cipher**: AES e RSA;
* **Digest**: MD5, SHA1, SHA256 ;
* **Signature**: PKCS1.

### totalcross.db e totalcross.sql

The **totalcross.db** package has SQLite Java implementation, the most widely used portable database in the world. Allows you to use SQL commands to manipulate data files lightly and with low memory consumption.

The t**otalcross.sql** package has JDBC implementation for use with SQLite - SQLiteUtil - as you can see in the code example below:

```java
public class DatabaseManager {

	public static SQLiteUtil sqliteUtil;

	static {
		try {
			sqliteUtil = new SQLiteUtil(Settings.appPath, "test.db");
			Statement st = sqliteUtil.con().createStatement();
			st.execute("create table if not exists person (cpf varchar)");
			st.close();

		} catch (SQLException e) {
			e.printStackTrace();
		}
	}
}
```

To learn more about SQLite, how to implement SQLite Useful, creating applications with database and CRUD just read the link session below:

{% content-ref url="/pages/-L\_mh8SzEd9PwojW-uEz" %}
[Broken mention](broken://pages/-L_mh8SzEd9PwojW-uEz)
{% endcontent-ref %}

### totalcross.io

The totalcross.io package concentrates the classes used in input and output.

* ByteArrayStream
* DataStream&#x20;
* File&#x20;
  * BufferedStream&#x20;
* LineReader&#x20;
* device.bluetooth&#x20;
* device.gps&#x20;
* device.printer&#x20;
* device.scanner

### totalcross.json

In this class we have the json library in Java, a lot used in the creation of Web Services through Rest. To understand better, visit the session below:

{% content-ref url="/pages/-LfujQe-oCmF7vQQdfi5" %}
[JSON](/master/documentation/apis/json)
{% endcontent-ref %}

### totalcross.map

Totalcross.map supports GoogleMaps and Waze. You can better understand by clicking on the session below:

{% content-ref url="/pages/-LeKpB\_bHYYG7MLKK1OB" %}
[Maps](/master/documentation/apis/maps)
{% endcontent-ref %}

### totalcross.net&#x20;

It is in the package totalcross.net where the connection classes are. Are they:

* Socket FTP;
* HTTPStream;
* ServerSocket;
* mail (pop3);
* SSL

### totalcross.phone&#x20;

The classes responsible for handling telephones are:

* CellInfo&#x20;
* Dial&#x20;
* SMS

### totalcross.sys&#x20;

The totalcross.sys package contains the utility and usage classes for Virtual Machine. Are they:

* Convert&#x20;
* Setting&#x20;
* Time&#x20;
* VM

### totalcross.unit&#x20;

The classes responsible for building unit tests are in the totalcross.unit package. The classes are:&#x20;

* TestCase
* TestSuite
* UIRobot

### totalcross.util&#x20;

Utilities classes

* Date Hashtable / Vector
* IntHastable / IntVector&#x20;
* Random&#x20;
* Collections&#x20;
* concurrent.Lock&#x20;
* BigDecimal / BigInteger&#x20;
* PDFWritter&#x20;
* Regex&#x20;
* Zip/ZLib/GZip

### totalcross.xml

In the package totalcross.xml are the classes responsible for XML handling. They are:

* XMLRPC com Axis&#x20;
* SOAP
* XMLTokenizer

## References

* For a better understanding, see the [javadoc](http://rs.totalcross.com/doc/index.html)


# API Rest

### Verbs

HTTP verbs are the request methods we use along with the endpoints to access a particular api route.

| Endpoint | Verbs  | Action                    |
| -------- | ------ | ------------------------- |
| /get     | GET    | Retrieves new information |
| /post    | POST   | Create new information    |
| /put     | PUT    | Change an information     |
| /delete  | DELETE | Delete information        |

### Requisitions

One of the ways to make requests is to create **PressListener** for Button, in the example below I will demonstrate how to get the response of the request in a variable and display in a Label

{% code title="PressListener" %}

```java
//String uri = Requisition URL
//HttpMethod httpMethod = HTTP Verbs
    PressListener getPressListener(final String url, String httpType) {
        return (e) -> {
            //msg variable will be responsible for storing the request response
            String msg = "";

            try {

                HttpStream.Options options = new HttpStream.Options();
                options.httpType = httpType;

                HttpStream httpStream = new HttpStream(new URI(url), options);
                ByteArrayStream bas = new ByteArrayStream(4096);
                bas.readFully(httpStream, 10, 2048);
                String data = new String(bas.getBuffer(), 0, bas.available());

                Response<ResponseData> response = new Response<>();
                response.responseCode = httpStream.responseCode;
                
                if (httpStream.responseCode == 200){
                        response.data = (JSONFactory.parse(data, ResponseData.class));
                        
                        //Accessing the answer and picking up the information.
                        msg += "Url: " + response.data.getUrl() + "\n";
                        msg += "Origin: " + response.data.getOrigin();
                }
            } catch (IOException e1) {
                    msg = "erro";
            } catch (InstantiationException ex) {
                ex.printStackTrace();
            } catch (InvocationTargetException ex) {
                ex.printStackTrace();
            } catch (NoSuchMethodException ex) {
                ex.printStackTrace();
            } catch (IllegalAccessException ex) {
                ex.printStackTrace();
            }

            lblResult.setText(msg);
            lblResult.setRect(KEEP, KEEP, PREFERRED, PREFERRED);

        };
    }
    
    public static class Response<T> {
        public T data;
        public int responseCode;
    }

```

{% endcode %}

Creating the packet to receive the response in order to handle the data obtained from the request

{% code title="Structures" %}

```
└── src
    └── main
        └── java
            └── com.your_company_name.your_name_app
                .
                .
                .
                └── ResponseData
                    └── Args
                    └── ResponseData
```

{% endcode %}

and now create the class to store the information

{% tabs %}
{% tab title="ResponseData class" %}

```java
package com.totalcross.RestApi.ResponseData;

public class ResponseData {

    Args args;
    String origin;
    String url;

    public Args getArgs() {
        return args;
    }

    public void setArgs(Args args) {
        this.args = args;
    }

    public String getOrigin() {
        return origin;
    }

    public void setOrigin(String origin) {
        this.origin = origin;
    }

    public String getUrl() {
        return url;
    }

    public void setUrl(String url) {
        this.url = url;
    }
}


```

{% endtab %}

{% tab title="Args class" %}

```java
package com.totalcross.RestApi.ResponseData;

public class Args {

    private String args;

    public String getArgs() {
        return args;
    }

    public void setArgs(String args) {
        this.args = args;
    }

}


```

{% endtab %}
{% endtabs %}

Now just put that pressListener on your button by changing only the endpoint and the verb, see the example below

```java
@Override
    public void initUI() {
        String binUrl = "http://httpbin.org";

        Button btnGet = new Button("GET");
        btnGet.addPressListener(getPressListener(binUrl + "/get", HttpStream.GET));
        add(btnGet, LEFT, AFTER, FILL, fmH * 3);

        Button btnPost = new Button("POST");
        btnPost.addPressListener(getPressListener(binUrl + "/post", HttpStream.POST));
        add(btnPost, LEFT, AFTER, FILL, fmH * 3);

        Button btnPut = new Button("PUT");
        btnPut.addPressListener(getPressListener(binUrl + "/put", HttpStream.PUT));
        add(btnPut, LEFT, AFTER, FILL, fmH * 3);

        Button btnDelete = new Button("DELETE");
        btnDelete.addPressListener(getPressListener(binUrl + "/delete", HttpStream.DELETE));
        add(btnDelete, LEFT, AFTER, FILL, fmH * 3);


        lblResult = new Label(" ");
        add(lblResult, LEFT, AFTER);
    }
```

### References&#x20;

* See the complete API code remainder with TotalCross in [GitHub](https://github.com/TotalCross/ApiSample).


# Asynchronous Task

Executing background tasks in order to not lock the Main Thread.

## Using AsyncTask class to execute background tasks&#x20;

In order to execute task that can take a few seconds to be completely executed, one must run it apart from the main thread, i.e, the thread responsible for painting components. Executing this kind of task in the main thread may cause a non-good user experience, once the application user may be unable to use and see any progress while the task is being executed.&#x20;

To avoid such an obstacle, TotalCross provides AsyncTask class, which is a helper to execute task in an asynchronous way. By using AsyncTask, the user can easily execute asynchronous task without complex manipulation of threads and, consequently, not locking the main thread. See the example bellow to learn how to use it.

{% hint style="info" %}
Copy and paste this code inside a [Container](/master/documentation/apis/control/container) instance.
{% endhint %}

```java
Button dldButton = new Button("download zip");
add(dldButton, CENTER, CENTER);

final ProgressBar progressBar = new ProgressBar();
add(progressBar, CENTER, AFTER + UnitsConverter.toPixels(DP + 16),
        PARENTSIZE + 80, PREFERRED);

dldButton.addPressListener((c) -> {
    new AsyncTask()<Void, Void, Void> {
        int progress = 0;
        UpdateListener updateListener = null;

        @Override
        protected Object doInBackground(Object... objects) {
            HttpStream.Options o = new HttpStream.Options();
            o.httpType = HttpStream.GET;
            final String url = "<INSERT AN URL TO DOWNLOAD A ZIP FILE>";

            if(url.startsWith("https:"))
                o.socketFactory = new SSLSocketFactory();

            try {
                HttpStream p = new HttpStream(new URI(url));
                File f = new File("file.zip", File.CREATE_EMPTY);
                int totalSize = p.contentLength;
                byte [] buff = new  byte[4096];
                BufferedStream bs = new BufferedStream(f, BufferedStream.WRITE, 4096);
                int counter = 0;
                while(true) {
                    int size = p.readBytes(buff, 0, buff.length);
                    counter += size;
                    progress = (int)((counter/(double)totalSize)*100);
                    if(size <= 0) break;
                    bs.writeBytes(buff, 0, size);
                }
                progress = 100;
                bs.close();
                p.close();
                f.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
            return null;
        }

        @Override
        protected void onPreExecute() {
            dldButton.setEnabled(false);
            MainWindow.getMainWindow().addUpdateListener(updateListener = (elapsed) -> {
                progressBar.setValue(progress);
            });
        }

        @Override
        protected void onPostExecute(Object result) {
            dldButton.setEnabled(true);
            MainWindow.getMainWindow().removeUpdateListener(updateListener);
        }
    }.execute();
});
```

Once method execute is called, before executing the asynchronous task, *onPreExecute* method is also called adding an *UpdateListener* to update the component [`ProgressBar` ](/master/documentation/components/progress-bar)in the adequate time interval trough the variable *progress*. The button dldButton is disabled to avoid user execute the same task many times unnecessarily. &#x20;

When the file is completely downloaded, the function *onPostExecute* is called removing the *UpdateListener*  and reenabling the button *dldButton.*


# Camera

### Overview

This class is used to enable the camera of the underlying device. The following platforms are supported: Android and iOS. It is not possible to use the webcam on PC platforms (JavaSE, Windows XP, Vista, Seven, 8, and Linux).

Note that you can easily rotate the image to put it in portrait mode, using the **Image.getRotatedScaledInstance( )** method, after retrieving the image. You may change the following options: **initialDir**, **defaultFileName** (must end with .jpg), and **resolutionWidth** x **resolutionHeight** (possible values are 320x240, 640x480, 1024x768, 2048x1536; different values defaults to 640x480). All other options are ignored.

On Android you can set the **defaultFileName**, **stillQuality**, **resolutionWidth** and **resolutionHeight**. All other options are ignored. You can call the **getSupportedResolutions( )** method to see the resolutions that are available on the device.

On iOS there’s no way to return the supported resolutions; it will take a photo using the default camera’s resolution, and then will resize to the resolution defined in **resolutionWidth** x **resolutionHeight**, keeping the camera’s aspect ratio. On iOS you can specify the **defaultFileName** with a path or just the name, or use a system-generated name. On iOS it is not possible to record a movie, only to take pictures.

**This class only has de default constructor. The other interesting fields are:**

* title The title to display in the window opened for the camera.<br>
* stillQuality Defines the quality of the image. It can be equal to CAMERACAPTURE\_STILLQUALITY\_DEFAULT (default quality), CAMERACAPTURE\_STILLQUALITY\_LOW (low quality), CAMERACAPTURE\_STILLQUALITY\_NORMAL (normal quality), or CAMERACAPTURE\_STILLQUALITY\_HIGH (high quality).<br>
* videoType Can be one of CAMERACAPTURE\_VIDEOTYPE\_ALL (produces video clips that match video profiles, using just the video resolution for the match criteria, the default value) CAMERACAPTURE\_VIDEOTYPE\_STANDARD (produces high-quality video clips used for home movies and e-mail video messaging, using a video encoder such as the Windows Media encoder), or CAMERACAPTURE\_VIDEOTYPE\_MESSAGING (Produces video clips used for Multimedia Messaging Service (MMS) video messaging, which require a video encoder that conforms to the 3rd Generation Partnership Project (3GPP) specification on <http://go.microsoft.com/fwlink/?LinkId=32710>).<br>
* videoTimeLimit Maximum time limit for recording a video.<br>
* captureMode Can be one of CAMERACAPTURE\_MODE\_STILL (only picture, the default value), CAMERACAPTURE\_MODE\_VIDEOONLY (no sound), or CAMERACAPTURE\_MODE\_VIDEOWITHAUDIO (video and sound).<br>
* allowRotation Use this on Android only. If false, the camera buttons will be on landscape. If true, the camera buttons will follow the device current rotation when the camera is opened.<br>

![](https://totalcross.com/documentation/en/api/img/xcamera.png.pagespeed.ic.fAne0JJDiH.png)

### The class **Camera** only has one method:

| Type                  | Name                       | Description                                                                                                                                                          |
| --------------------- | -------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| **String**            | click( )                   | Takes a photo or records a video based on the members set. It returns a string with the file name where the image or video is located, or null if the user canceled. |
| **static String\[ ]** | getSupportedResolutions( ) | Gets the supported resolutions on the current device.                                                                                                                |

## References

* To know more details read its [JavaDocs](https://rs.totalcross.com/doc/totalcross/ui/media/Camera.html).
* For more details, check in [Github project](https://github.com/TotalCross/TCSample/blob/master/src/main/java/totalcross/sample/components/ui/CameraSample.java).


# Control

![](/files/-LaueYXyzaLOXR1oKqBy)


# Main Window

## Overview

Every TotalCross program must have one and only one class that extends totalcross.ui. MainWindow. It is the interface between the VM and the TotalCross program: it receives all events and dispatches them.

## Usage

```java
import totalcross.ui.*;
public class MainWindowSample extends MainWindow {
	
	public MainWindowSample() {
		setUIStyle(Settings.MATERIAL_UI);
		setDefaultFont(Font.getFont(Fonts.FONT_DEFAULT_SIZE));
	}
	
	static {
		Settings.applicationId = "MWSP";
		Settings.appVersion = "1.0.1";
		Settings.iosCFBundleIdentifier = "com.totalcross.sample.mainwindowsample";
	}
	
	public void initUI() {
		// add controls here
	}
		​
	public void onExit() {
		// close stuff here
	}
}
```

The VM first calls the default `MainWindow` constructor (in this case, `MainWindowSample()`), and then queues a timer event, which calls the `initUI()` method inherited from the `Container` class. **You must initialize the entire user interface in the `initUI(`) method.**

Initializing the UI in the constructor may hang the application and some operations can only be performed after the `initUI(MainWindow)` method is reached.

The **`onExit()`** method is called when the VM exits under normal circumstances, that is, if the user closes the application or the programmer terminates the application using `exit()` or `exec()` or even when the application is interrupted by an exception treated.

{% hint style="warning" %}
&#x20;In abnormal circumstances where a fatal error occurs by resetting the device, the `onExit()` method is not called. When this is called, all segments are already dead.
{% endhint %}

At **line 5** we use the **`setUIStyle()`** method to assign the style of our application as `Settings.MATERIAL_UI` **and so all components and effects will be in the Google** [**Material Design standard**](https://blog.totalcross.com/en/material-o-layout-da-google/)**.**

To change the font used by all the created controls, you must call the `setDefaultFont()` method on **line 6**. In this case, we are setting the default font size that we defined in the **Fonts class**. To better understand this process, just [**click here**.](https://totalcross.gitbook.io/playbook/guideline/colors-fonts-and-images#fonts)

Still, inside the constructor, you can define MainWindow title and/or style using `setTitle()` and `setBorderStyle()` methods however **there is performance loss**. To reverse this loss, you can use the `super(title, style)` method, but this method can not be used with `setDefaultFont()`. Styles for border can be:

* Window\.NO\_BORDER;
* Window\.RECT\_BORDER;
* Window\.ROUND\_BORDER;
* Window\.TAB\_BORDER;
* Window\.TAB\_ONLY\_BORDER.

{% hint style="info" %}
But these decisions must be made on the **basis of the design of your application**. TotalCross recommends that you all follow [**Material Design.**](https://blog.totalcross.com/en/material-o-layout-da-google/)
{% endhint %}

## The Application Lifecycle

The application on TotalCross has a predefined life cycle, handled by defined methods in MainWindow:

| methods                       | Definition                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                         |
| ----------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| initUI():                     | called when the application starts.                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                |
| onMinimize():                 | called when the user press the home key, or when a call is received, or when the screen turns off. On Android and Windows 32, the application execution is not paused. On Windows Phone 8 and iOS, it is paused.                                                                                                                                                                                                                                                                                                                                   |
| onResume():                   | called after the call ends, the screen is turned on again, or the program was exited softly on Android. It is also called again if the user clicks on the application icon on Android and iOS. On WP8, it is necessary to press back in the main menu and click on the opened application. Clicking on its icon in the list of applications will kill the current instance and relaunches it again.                                                                                                                                                |
| onExit():                     | <p>called when the system decides that is time to finish the application. If the home key was pressed, this method is called when another TotalCross application is launched on Android if the application is not installed as a single package. <br><br>If the user press the home key and then forces the application to stop (by going to the Settings/Applications) on Android and iOS, then all Litebase tables may be corrupted (actually, no data is lost, but a TableNotClosedException will be issued). So, it’s a good thing to call</p> |
| LitebaseConnection.closeAll() | in your Litebase instances in the onMinimize() method and recover them in the onResume() method. Just remember that all prepared statements, row iterators and result sets will be invalid and can’t be reused. Notice that the application might also be killed by the system if it’s on background.                                                                                                                                                                                                                                              |

On WP8, there is no way to kill an application. To kill it, you must restore it pressing back in the main menu and them openning the application again. Then, press back until finishing the application.

It is also a good practice to save all necessary data and application state so that the when the user goes back to the application it won’t need to do a task again, such as entering data again in a form which was lost when the application was closed by the system. Of course there are situations where the user must retype data, such as login and password and when using bank applications.

Remember that applications for Android, iOS, and Windows Phone 8 shouldn’t have an exit button or an exit option in the menu. The application should be designed to be opened all the time and only the system should close it when needed. Again, there are exceptions, for example when the user doesn’t agree with an eula and the application can’t continue running.

Finally, it is a good idea to map the device back key on Android and WP8 to go back to the last window/menu used. Just remember that on WP8 back is back, you just can use it to go back to the last screen used. On the first screen, back should exit the application. The only exception are games, where back during a game play goes to the pause window.

## References

* To know more details about totalcross.ui.MainWindow, read its [JavaDocs](https://rs.totalcross.com/doc/).


# Window

## Overview

As you already know, a TotalCross program with user interface consists of one and only one main window (a class that directly or indirecly extends MainWindow). This main window can pop up a window, and this new window can pop up another one, and so on. Windows in TotalCross are always modal, therefore, only the last popped up window can receive events and you cannot switch from the topmost Window to the previous without closing the topmost one.

Although the Window class extends Control, you can’t add a Window to a Container. Doing this results in a RuntimeException. To show a window, you must use the method `popup()` or the method `popupNonBlocking().`

If you want to know more about how differences between windows and container, how to navigate between interfaces and what are the best ways to handle containers and windows, just click on the link below:

{% content-ref url="/pages/-L\_ml9iy2SivE5II\_fAX" %}
[Separation of concepts: What is the best way to create UI interfaces?](/master/documentation/guides/app-architecture/container-x-window)
{% endcontent-ref %}

## Usage

### create a popup window class:

{% code title="TestWindow" %}

```java
class TestWindow extends Window{
	
	public void onPopup() {
	 	logo = new ImageControl(Images.logo_branco);
		logo.scaleToFit = true;
		logo.centerImage = true;
		logo.transparentBackground = true;
		add(logo, CENTER, CENTER, PARENTSIZE + 50, PARENTSIZE + 50);

		FadeAnimation.create(logo, true, null, 3000)
				.then(FadeAnimation.create(logo, false, this::onAnimationFinished, 3000)).start();
	}
	
	public void onAnimationFinished(ControlAnimation anim) {
		this.unpop(); // a WINDOW_CLOSED event will be posted to this PARENT window.
	}
}
```

{% endcode %}

### Blocking

```java
public class Launcher extends MainWindow{
	Button btn;
	
	public void onEvent(Event e){
		if (e.target == btn){
			TestWindow tw = new TestWindow();
			tw.popup(); // this line is only executed after the window is closed.
		}
	}
}
```

### Non-blocking

To use it non-blocking (the execution continues right after the popup command, even with the window still open):

```java
public class Launcher extends MainWindow
{
	TestWindow tw;
	public void initUI()
	{
		tw = new TestWindow();
		tw.popupNonBlocking(); // this line is executed immediately
	}
	public void onEvent(Event event)
	{
		if (event.target == tw && event.type == ControlEvent.WINDOW_CLOSED)
		{
			// any stuff
			break;
		}
	}
}
```

Blocking popup may be use in InputBox/MessageBox classes, while non-blocking popup is used in MenuBar and other classes.&#x20;

Important note: you can’t use `popup()` with a delay to unpop it. In this case, the correct would be to use `popupNonBlocking()`:

```java
mb = new MessageBox(...);
mb.popupNonBlocking();
Vm.sleep(5000); // or do something else
mb.unpop();
```

If you use `popup()` in this specific case, the VM will hang.

## Others features of the Window Class

* Windows can have a title that can be set by the method setTitle(String title) (which calls repaint()) or passed to the constructor.<br>

* The window border can be selected from one of the multiple styles shown below, by using the setBorderStyle(byte borderStyle) method or passing the desired style to the Window constructor. The parameter value can be NO\_BORDER, RECT\_BORDER, ROUND\_ BORDER, TAB\_BORDER, TAB\_ONLY\_BORDER, HORIZONTAL\_GRADIENT, or VERTICAL\_ GRADIENT. To retrive it, use getBorderStyle().<br>

* There are two constructors: the default one, that creates a window with no title and no border, and one constructor with both title and border parameters.

  * `Window()`;
  * `Window(String title, byte borderStyle)`

* Windows can be moved around the screen by dragging the window’s title. If the window has no title, it can’t be moved. You can make a titled window unmovable by calling the makeUnmovable() method.<br>

* The title font can be changed using the setTitleFont() method. To retrive it, use getTitleFont(). By default, the font is the one used by the main window, with bold style.<br>

* Only one control can hold the focus at a time. To change focus to another control, use the setFocus(Control c) method (this can also be done through the requestFocus() method in the totalcross.ui.Control class). When a user types a key, the control with focus gets the key event. Calling this method will cause a FOCUS\_OUT control event to be posted to the window’s current focus control (if one exists) and will cause a FOCUS\_IN control event to be posted to the new focus control. The getFocus() method returns the control that currently owns the focus.<br>

* The rectangle area excluding the border and the title is defined as the client rectangle. You can get it with the getClientRect() method.<br>

* A window can be popped up by calling the popupNonBlocking() method and can be unpopped by calling the unpop() method. The popup process saves the area behind the window that is being popped up and the unpop process restores that area. The unpop() method posts a ControlEvent.WINDOW\_CLOSED event to the caller window. The popupNonBlocking() method can be called like this.popupNonBlocking(). Calling unpop() when only the MainWindow is active does nothing.<br>

* A window can also be popped up by calling the popup() method, and be unpopped by the same unpop() method described above. The big difference is that in popupNonBlocking(), the program execution continues to the next line, while in popup(), the program execution is halted and only continues when the popped up window is dismissed. Menu, MessageBox, ComboBox, and ComboBoxDropDown are popped up using popupNonBlocking(), because execution does not need to be halted. InputDialog, Calendar, and Calculator are usually popped up using popup() because the user may want to get the result of the dialog in an easy way.\
  You can’t use `popup()` to popup alternating windows that call each other recursively. For example, suppose that from win1 you call win2.popup(), then at win2 you call `unpop()` and then win1.`popup()`. Then, from win1 you do `unpop()` again and win2.popup(), and so on. This will lead to an OutOfMemoryError on the device due to a native stack overflow. To fix this, just replace the popup by popupNonBlocking().<br>

* The topmost window (the one who receive events) can be obtained with the static method `getTopMost().` To check if this window is the topmost, use the `isTopMost()` method.<br>

* Try `setGrabPenEvents()` for settting to a control to redirect all pen events directly to it. This method speeds up pen event processing. Used in Whiteboard class.<br>

* You may check if this window is visible using the isVisible() method. This method is inherited from totalcross.ui.Control, but it simply checks if the current window is the topmost one.<br>

* Each window can have a menu attached by using the method setMenuBar(). The menuBar can be made visible programatically by calling the popupMenuBar() method.<br>

* Suppose you wish to allow the user to abort a task being executed by pressing. You can use the method pumpEvents() to process all events in the queue. This method is used to implement a blocking Window. Here is an example:\
  `while(someCondition)` \
  &#x20; `Event.pumpEvents(); Event.pumpEvents();`

* The methods getPreferredWidth() and getPreferredHeight() have a special meaning for the Window class. They return the minimum width/height needed for the correct display of this window. getPreferredWidth() returns the width of the title (if any) plus the width of the border (if any). getPreferredHeight() returns the height of the title (if any) plus the height of the border (if any).

## **Protected methods**

There are some useful protected methods that may be implemented by controls that extend totalcross.ui.Window. Those methods are placeholders and there is no need to call the super method.

| **Methods**                     | Definitions                                                                                                                                                                                                                                                                                                                                                                                                       |
| ------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| onClickedOutside(int x, int y): | This method is used in popup windows. If the user clicks outside the window’s bounds, this method is called giving the absolute coordinates of the clicked point. There are two options: If you had handled the action, return true in this method. Otherwise, false must be returned and if the beepIfOut member is true, a beep is played (in other words, beepIfOut can be set to false to disable this beep). |
| onPopup():                      | Called just after the behind contents are saved and before the popup process begin. When this method is called, the topmost window is still the parent of the window being popped up.                                                                                                                                                                                                                             |
| postPopup():                    | Called after the popup process ended. When this method is called, the popped up window is fully functional. It is a good place to put a control.requestFocus() to make the window popup with the focus in a default control.                                                                                                                                                                                      |
| onUnpop():                      | Called just before the unpop process begin.                                                                                                                                                                                                                                                                                                                                                                       |
| postUnpop():                    | Called after the unpop process ended. When this method is called, the unpopped window has gone away and the parent window is currently the topmost.                                                                                                                                                                                                                                                               |
| postPressedEvent():             | Posts a ControlEvent.PRESSED event on the focused control.                                                                                                                                                                                                                                                                                                                                                        |

A very common mistake is to popup a window without setting its bounds. If no bounds are set, the window will not receive events.

## **Other Members**

The other members that can be used (all public and some protected) of the Window class are explained here:

| **Members**              | Definitons                                                                                                                                                                                            |
| ------------------------ | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| needsPaint               | <p></p><p>true if there are any controls marked for repaint (some area of the window is invalidated).<br></p>                                                                                         |
| tempTitle                | A temporary title that will be displayed when the Window pops up. It will be replaced by the original title when it is closed.                                                                        |
| topmost                  | Stores the topmost window.                                                                                                                                                                            |
| firstFocus               | The control that should get focus when a focus traversal key is pressed and none has focus.                                                                                                           |
| canDrag(protected)       | <p></p><p>If true and if this is a popup window, the user is allowed to drag the title and make the window move around.<br></p>                                                                       |
| cancelPenUp              | If true, the next PEN\_UP event will be ignored. This is used when a PEN\_DOWN cancels a flick, or if a drag-scrollable control needs to cancel the next pen\_up during a drag-scrolling interaction. |
| gradientTitleStartColor  | The starting and ending colors used to fill the gradient title.                                                                                                                                       |
| gradientTitleEndColor    | The starting and ending colors used to fill the gradient title.                                                                                                                                       |
| titleColor               | The title color depends on the border type: it will be the foreground color if NO\_BORDER is set; otherwise, it will be the background color.                                                         |
| titleGap                 | A vertical gap used to increase the title area. Defaults to fmH/2 on Android and 0 on other user interface styles.                                                                                    |
| titleAlign               | The title horizontal alignment in the window’s title area. It can be LEFT, CENTER, or RIGHT, and you can use an adjustment on the value (E.G.: LEFT+5).                                               |
| headerColor, footerColor | Has the header and the footer colors when on Android style and border type is ROUND\_BORDER. Not used on other styles.                                                                                |
| fadeOtherWindows         | Set to true to make the other windows be faded when the window appears.                                                                                                                               |
| <p>fadeValue<br></p>     | The value used to fade the other windows. Defaults to 128.                                                                                                                                            |
| robot                    | The UIRobot instance that is being used to record or play events.                                                                                                                                     |

Never mess with the public member zStack. It is used to store the windows that are currently popped up. It is made public because the totalcross.Launcher class uses it.

## How controls inside a window are repainted:

* The programmer calls the `repaint()` method of some controls, or a control is clicked and marks itself for repaint.<br>
* The `damageRect(`) method in class window creates a rectangle (stored in the paintX, paintY, paintWidth and paintHeight members) with the union of the bounds of all controls marked for repaint.<br>
* The next time a VM event is posted, the `_doPaint()` method of the topmost window is called. This method paints the window’s title/border (if any) and calls the onPaint() method of all containers and controls that lies inside the rectangle area marked for repaint. This explains why nothing in the window is updated when you receive events directly from a native library (the Scanner class, for example). Because the VM is not receiving the event, it never validates the window. In these cases, you must update the window yourself, calling repaintNow() or the validate methods.

Many classes in the totalcross.ui package extend totalcross.ui.Window. Examples of such classes are `CalculatorBox` and `CalendarBox`. Other good examples are `ComboBoxDropDown` and `MessageBox`.

It’s important to be aware that it is not a good practice to create classes that extend Window if they will occupy the whole screen, because they use a lot of memory to store the underlying area. Opening the menu may lead to time-consuming redraws of all opened windows due to out-of-memory problems. In these cases, it is better to use `Containers`.


# Container

## Overview

The container is a control that contains child controls. It is possible to adjust its transparency, screen transition effects, borders and background style.

If you want to know more about how differences between windows and container, how to navigate between interfaces and what are the best ways to handle containers and windows, just click on the link below:

{% content-ref url="/pages/-L\_ml9iy2SivE5II\_fAX" %}
[Separation of concepts: What is the best way to create UI interfaces?](/master/documentation/guides/app-architecture/container-x-window)
{% endcontent-ref %}

## Usage

{% code title="Container" %}

```java
class ContainerSample extends Container{
	
	@Override
    public void initUI() {
      try {
            ImageControl logo = new ImageControl(new Image("path_of_your_logo_img"));
            logo.scaleToFit = true;
            logo.centerImage = true;
            logo.transparentBackground = true;
            add(logo, CENTER, CENTER, PARENTSIZE + 50, PARENTSIZE + 50);
        } catch (ImageException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}
```

{% endcode %}

## Features of Container

* [**How to navigate between screens**](https://app.gitbook.com/@totalcross/s/playbook/~/drafts/-LeSnZoHZefj9mq9OlAt/primary/faq#how-to-navigate-between-screens-containers-and-windows)
* **Container characteristics are assigned to child controls**

### Method

Some methods that are most commonly used

| name                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                            | Description                                                                                                                                                                                                                                                                                                                                                                                                                                                                    |
| ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
| <p>add(Control control, int x, int y, int w, int h, Control relative);</p><p></p><p><a href="https://rs.totalcross.com/doc/totalcross/ui/Container.html#add-totalcross.ui.Control-">add</a>(<a href="https://rs.totalcross.com/doc/totalcross/ui/Control.html">Control</a> control)</p><p><br>add(Control control, int x, int y)<br><br><a href="https://rs.totalcross.com/doc/totalcross/ui/Container.html#add-totalcross.ui.Control-int-int-totalcross.ui.Control-">add</a>(<a href="https://rs.totalcross.com/doc/totalcross/ui/Control.html">Control</a> control, int x, int y, <a href="https://rs.totalcross.com/doc/totalcross/ui/Control.html">Control</a> relative)<br><br>add(Control control, int x, int y, int w, int h)</p><p></p> | Adds the control on the screen where the parameter x is the positioning of the control in the container in relation to the x axis, the parameter y is the positioning of the control in the container in relation to the y axis, parameter w is the length of the component, parameter h represents the height of the component and the relative parameter is to change the reference of the control to add on the screen (by default the relative is the last control added). |
| setBackForeColors(Color back, Color fore)                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                       | Assigns the color of the back parameter to the container background and the color of the fore parameter to the forecolor of the container. It is interesting to remember that the children of the container inherit the characters of the same.                                                                                                                                                                                                                                |
| <p>setBackColor(Color back);                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                    |                                                                                                                                                                                                                                                                                                                                                                                                                                                                                |

</p><p></p>                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                        | Assigns the color of the back parameter to the container background                                                                                                                                                                                                                                                                                                                                                                                                            |

## Referencies

You can see more information in [javaDoc](https://rs.totalcross.com/doc/totalcross/ui/Container.html)


# GPS

### Overview

**GPS** is a class that retrieves GPS coordinates read from Android, WP8, and iOS native API. This class only retrieves data updating the internal fields. If you want to display that data, you may use the **GPSView** class.

If the GPS fails connecting to the satellites, and the phone has signal, you can use the cell tower location as a rough location. The precision varies between 50m to 3km, depending on the phone location. In this case, you can get the latitude and longitude using **CellInfo.toCoordinates()** on Android and Windows 32. This won’t work on other platforms. Don’t forget to turn on the GPS, going to somewhere similar to Settings / Security & Location / Enable GPS satellites. You won’t be able to use if if it’s off in the settings.

### GPS class

Here is an example of GPS usage:

{% code title="GPS\_SAMPLE" %}

```java
new Thread()

{
	public void run()
	{
		gps = new GPS();
		for (int i = 0; i < 60*2 && gps.location[0] == 0; i++) // wait 60s
		{
			Vm.safeSleep(500);
			try
			{
				gps.retrieveGPSData();
			}
			catch (Exception eee)
			{
				eee.printStackTrace();
				break;
			}
		}
	}
}.start();
```

{% endcode %}

### Atributes

| Type      | Name       | Description                                                                          |
| --------- | ---------- | ------------------------------------------------------------------------------------ |
| int       | satellites | Number of satellites                                                                 |
| double\[] | location   | Stores the location - latitude on first index (0) and longitude on second index (1). |
| double    | direction  | Stores the direction in degrees from the North.                                      |

### methods

| **Type** | Name              | Description                                                                                              |
| -------- | ----------------- | -------------------------------------------------------------------------------------------------------- |
| boolean  | retrieveGPSData() | Call this method to retrieve the data from the GPS, true if the data was retrieved, false if low signal. |
| void     | stop()            | Closes the underlying PortConnector or native api.                                                       |
| double   | getLatitude()     | Returns the latitude                                                                                     |
| double   | getLongitude()    | Returns the longitude                                                                                    |

## **References**

For more details, check out [JavaDoc](https://rs.totalcross.com/doc/).


# HTTPS and SSL

## Overview

The TotalCross SSL native library is a wrapper library of the great axTLS package. The axTLS embedded SSL project written by Cameron Rich is a highly configurable client/server TLSv1 library designed for platforms with small memory requirements (click [here ](http://axtls.cerocclub.com.au/index.htm)for more details).

The original package supports:

* Linux;
* Win32;
* Solaris;&#x20;
* Cygwin.

This native library adds support for **SSL** **(Secured Sockets Layer)** communications to secure data transfers between authenticated devices and/or servers.

## Security background

For general information about the features of **TLS** (**Transport Layer Security**) and its usage, you may read the [Wiki pag](http://en.wikipedia.org/wiki/Transport_Layer_Security). If you are lucky, you may even read a good translation in your personal language.

The english version provides a basic protocol description for everyone. For those who want to go further, the reference is the [TLS protocol version 1.0 RFC 2246](http://tools.ietf.org/html/rfc2246).

Basically, TLS **allows secured and authenticated communication between two components generally so-called client & server**. It relies on X509 certificates, their associated **private keys** to encrypt and associated public keys to decrypt exchanged data. The certificates could be self signed or signed by an Authority known as **CA (Certification Authority)** that have to be trusted.

Insofar the subject of SSL based security is well documented on the web, we won’t go further in the TLS description and invite people interrested in diving more deeply in secured communications to read the plenty of articles, books and HOWTOs available on the Internet. For general information about the features of TLS (Transport Layer Security) and its usage, you may read the [Wiki page](http://en.wikipedia.org/wiki/Transport_Layer_Security). If you are lucky, you may even read a good translation in your personal language.

## Authenticate Certificates

o connect to the Google API, if it is an HTTPS protocol, you will need to indicate that the SSL / TLS certification issuer is reliable.

### **But how does certificate authentication work?**

When you trust a certification, you are actually confining the issuer to it. This is because certification acts as a chain. You say that the certifying entity is reliable and therefore, all the certificates generated by it, are.

An example of this is GlobalSign, a certification authority (CA). It issues a root certificate to Google and with this, Google can issue other certificates through it.

The root certificate is called the Google G3 Authority. Therefore, for HTTPS to work you need to trust the certificate or anyone in the certification chain.

### **Step by step**

* Open the URL in the browser and click on the padlock that appears (next to the URL) and then on "Valid", just below "Certificate". There you will find the data, such as the name of the issuer and with this, you will, in your code, indicate the issuer as reliable.&#x20;

![Step 1](/files/-LgXkwiEZXgXBeW8ULEX)

* To find the certificate, simply go through the certification path and click on view certificate and then in detail and then copy to file.

![Step 2.1](/files/-LgXlEbT0CihZp4abkpO)

![Step 2.2](/files/-LgXlIYZEsDMeOJtTTqL)

* After you click Copy to File, you will see some options, click the one that has "base64 encoded".

![Step 3](/files/-LgXlQcwE-pHaTix7av2)

* Once saved, grab the .cer file and place it inside the Authorities class in loop execution.<br>

  <pre class="language-java" data-title="Step 4"><code class="lang-java">//Load all know cases
  for(int c = Authorities.certificates.lenght - 1; c >= 0; c++){
  }
  </code></pre>

## Generating security material

We will concentrate on the more general deployment of X509 client or server certificates signed by a Certification Authority (CA) (click [here](<http://en.wikipedia.org/wiki/X.509 >) for more details).&#x20;

First we will have to create our own CA, that could be replaced by any "well known" commercial CA such as Verisign, Thawte, etc, if you have the need for a public authority.

We will use [openssl ](https://learn.totalcross.com/master/documentation/apis/www.openssl.org)as security engine to generate the security material involved in certificate based authentication/encryption. It’s a well spread SSL implementation providing powerfull tools to create and manage all kinds of security materials available on many platforms.

## Create a private CA

Generate a self signed certificate that will be used as Certification Authority (CA). The authority will be valid for 10 years (approx 3650 days).

```php
bash$ openssl req -new -x509 -days 3650 -keyout cakey.pem -out cacert.pem
Generating a 1024 bit RSA private key
.++++++
.....++++++
writing new private key to ’cakey.pem’
Enter PEM pass phrase: xxxxx
Verifying - Enter PEM pass phrase: xxxxx
-----
You are about to be asked to enter information that will be incorporated into your certificate request.
What you are about to enter is what is called a Distinguished Name or a DN.
There are quite a few fields but you can leave some blank
For some fields there will be a default value,
If you enter ’.’, the field will be left blank.
-----
Country Name (2 letter code) [AU]:BR
State or Province Name (full name) [Some-State]:Rio de Janeiro state
Locality Name (eg, city) []:Rio de Janeiro
Organization Name (eg, company) [Internet Widgits Pty Ltd]:SuperWaba Ltda
Organizational Unit Name (eg, section) []:SuperWaba dev. department
Common Name (eg, YOUR name) []:SuperWaba Sample CA
Email Address []:guich@superwaba.com.br
```

The first entry is the private key password. The private key is used to sign other certificates to assert they are authentic. The private key is protected by a password as a further security because the CA private key is a main secret that have to be protected.

Next you will have to fill in X500 attributes describing the certificate subject. In our case, we enter information describing the SuperWaba CA (Certification Authority). Any agent trusting this CA, will authenticate certificates that have been signed by it through the CA embedded public key.

We now have two files, **cakey.pem** containing an encrypted version of the CA private key protected by a password and cacert.pem containing an X509 certificate embedding the CA public key that could be redistributed.

Finally, you have to create a text file named **ca.srl** with the content "00" for certicate signing counting, just execute the following command:

```php
bash$ echo “00” > ca.srl
```

## Create a client or server X509 certificate

First, you have to generate a new private key. SSL supports unencrypted and aes128/256 encrypted private keys.

```
bash$ openssl genrsa -aes128 -out mykey.pem 512
```

You may replace **-aes128** by **-aes256** for a stronger cipher, or remove **-aes128** at all to generate a private key that is not encrypted. When you ask for an encrypted key, you have to enter a password used in the ciphering. The last option represents the key size in bits, values between 512 and 4096 bits for a higher security are accepted, but always keep in mind that higher security implies longer processing times especially critical on embedded devices.

Next you have to generate a certificate request. This file could be transmitted to one of the commercial CA companies for signing or could be signed by our previously created private CA.

```
bash$ openssl req -new -out my.req -key mykey.pemAdd -x509
```

if you want to generate a self signed certificate if you don’t want to use a CA at all (in this case, you may name the file **mycert.pem** rather than **my.req**). Insofar, the **out** file will contain a finalized self-signed certificate rather than a certificate request.

Enter all information describing your client or your server component. The certificate request will be stored in the file **my.req.**

Finally, we will sign the certificate with the CA.

```
bash$ openssl x509 -CA cacert.pem -CAkey cakey.pem -CAserial ca.srl -req -in my.req -out mycert.pem -days 1460
```

## Principle of an X509 authentication/encryption

X509 authentication/encryption is based on public/private key encryption that have a great characteristic. Indeed, the data ciphered by either key could only be deciphered by the other one.

A software component that has to be authenticated, such as a secured server, may now be configured to deliver to any client the previously generated certificate (contained in **mycert.pem**). It also has to load the associated certificate private key. That private key is used to cipher data transmited to the client. On the other side, the client uses the public key embedded in the accepted server certificate to decipher the data from the server and cipher the data to be sent back to the server so that the server can decipher with its private key. If the client is configured to trust any certificate that have been signed by the signing CA, it will be able to authenticate any certificate using the CA public key.

The SSL package supports both PEM and DER encrypted materials.

[**DER** ](http://en.wikipedia.org/wiki/Distinguished_Encoding_Rules)is an ASN.1 encoding of information, [PEM](http://en.wikipedia.org/wiki/Privacy_Enhanced_Mail) is a **base64** encoding of a DER encoded data with a header "-----BEGIN " and a trailer "-----END " followed by a material type name. A PEM file may be de-encrypted or encrypted with AES128 or AES256 ciphers only.

LiteSSL also supports the pkcs8 encoding that is a private key encryption format. But it supports only one ciphering algorithm that is PBE-SHA1-RC4-128. Here is the command line to convert a PEM encoded private key into a pkcs8 encoded format. Always use the .p8 file suffix to identify the pkcs8 format.

```
bash$ openssl pkcs8 -topk8 -in mykey.pem -inform PEM -out mykey.p8
-outform DER -v1 PBE-SHA1-RC4-128
```

bash$ openssl pkcs8 -topk8 -in mykey.pem -inform PEM -out mykey.p8

-outform DER -v1 PBE-SHA1-RC4-128You will have to enter a password, that will be required to use the private key.

LiteSSL also supports pkcs12 that is a certificate/private key encryption format. But it supports only one ciphering algorithm that is PBE-SHA1-RC4-128. Here is the command line to convert certificate and its associate encoded private key into a pkcs12 encoded format. Always use the **.p12** file suffix to identify the pkcs12 format.

```
bash$ openssl pkcs12 -export -in server.pem -out server.p12 -name
"myserver" -inkey server.key -certpbe PBE-SHA1-RC4-128 -keypbe
PBE-SHA1-RC4-128
```

You will have to enter a password, that will be required to use the private key embedded in the pkcs12 encoded file.

## Restrictions

The Applet version is implemented on top of SUN’s JSSE. This TLS implementation has some limitations that prevent the use of some security material formats supported by SSL on devices. Thus, private keys have to be in pkcs8 format only. Moreover, they can’t be password protected. You have to add the -nocrypt option to the command line provided above to convert a PEM encoded private key to pkcs8 encoding.

## SSL usage

The **SSLUtil** class provides functions to get information about the TLS stack layer.

The first class to instantiate is **SSLClient** or **SSLServer** (not currently supported). This class represents an SSL client or server context both inheriting from the **SSLCTX** class that provides many SSL context common services. The main feature concerns the security material loading. Use **objLoad( )** to load material from files or memory. The arguments of this function are the material type (CA, X509 certificate, private keys, etc), the filename or the memory containing the material, and finally a password for private keys loading if they are password based encrypted.

To succeed the handshake with a server, you have to trust its self-signed certificate or trust the CA certificate who signed the server’s certificate.&#x20;

Use:

* **`objLoad(SSL_OBJ_X509_CACERT, “cacert.pem”, null)`** to trust the server’s signing CA. If the server requires client authentication, you will have to send your own client certificate;
* **`objLoad(SSL_OBJ_X509_CERT, “mycert.pem”, null)`** to load your client certificate;&#x20;
* **`objLoad(SSL_OBJ_RSA_KEY,“mykey.pem”, “pass”`)** to load the client certificate associated private key protected by the **pass** password.

Next, you have to call **`connect()`** on the context instance to create an SSL instance linked with a previously created socket.&#x20;

The SSL handshake starts immediatly to try to establish an authenticated/ciphered communication.

The SSL handshake succeeded if the `connect()` call returns an SSL instance and the **`handshakeStatus()`** function call on that instance returns **SSL\_OK**. Consequently, you may check the subject of the peer certificate with the **`getCertificateDN()`**&#x63;all to identify it and the context could be used to write and read ciphered data until the “dispose” call terminates the SSL communication. The peer receives a protocol alert to signal a link shutdown.

The SSL write of data returns the amount of bytes written or an error if the writing failed. The SSL read of data may return **SSL\_OK** that indicates that the read is not yet terminated and may be called again to achieve the reading of a block of decipherable data.

## References

* For more details, check out the **totalcross.net.ssl** package [JavaDocs](https://rs.totalcross.com/doc/index.html).


# JSON

## Overview

Json is a way to structure data quickly and with good readability and has a key/data structure very similar to the java hasmap or the python dictionary.

## How to use

the two ways to use JSON in TotalCross:

### Beans

You need to create the data beans that will be received in JSON

```java
//Where the data parameter is a variable that contains the JSON
Response response = JSONFactory.parse(data, Response.class);
```

You can see more abount this in [REST API](https://app.gitbook.com/@totalcross/s/playbook/apis/api-rest)

### JSON Object

```java
//Where the data parameter is a variable that contains the JSON
JSONObject jsonObject = new JSONObject(data);
```

You can use the variable jsonObject  like a hashmap.

## Referencies

* See a project on github using[ JSON](https://github.com/TotalCross/ApiSample)


# Maps

TotalCross currently does not have support for applications that need a dynamic map, but it is still possible to work with static map. In addition, we are working to integrate a new and improved navigation API in TotalCross.

The static map is an image captured by a request in an API that shows the map of the requested parameters.

{% content-ref url="/pages/-LeL-y36-0OL4MUOFoJN" %}
[Static Map](/master/documentation/apis/maps/static-map)
{% endcontent-ref %}

Old API using google Map currently deprecated.

{% content-ref url="/pages/-Lb8kS-QWThUpgNGA2WB" %}
[Maps - Deprecated](/master/documentation/apis/maps/maps)
{% endcontent-ref %}


# Maps - Deprecated

## Overview

You can use google maps to display a map in your app, and you can add some geometric shapes to your map

## Attributes

| Type    | Name                    | Description                                                                                                                                                    |
| ------- | ----------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| **int** | SHOW\_SATELLITE\_PHOTOS | Used in the flags argument of showRoute: shows the satellite photos                                                                                            |
| **int** | USE\_WAZE               | Used in the flags argument of showRoute: use waze to show the route of the current location to a target address. Note that the destination address is NOT used |

## Methods

| Return        | Name                                                                           | Description                                    |
| ------------- | ------------------------------------------------------------------------------ | ---------------------------------------------- |
| **int**       | toCoordI(Double v)                                                             |                                                |
| **boolean**   | showAddress(String address, boolean showSatellitePhotos)                       | Shows the given address in a separate viewer   |
| **boolean**   | showRoute(String addressI, String addressF, String traversedPoints, int flags) | Shows the route between two points.            |
| **boolean**   | showMap(MapItem\[] items, boolean showSatellitePhotos)                         | Shows an array of MapItem elements in the map. |
| **double\[]** | getLocation(String address)                                                    | Returns the location after searching Google.   |

## Nested Class

### MapItem

is an abstract class that will serve as inheritance for the classes below

#### Methods

| Type              | Name                       | Description             |
| ----------------- | -------------------------- | ----------------------- |
| **abstract void** | serialize(StringBuffer sb) | Creates a simple switch |

### Place

#### Attributes

| Type       | Name      | Description                                                                          |
| ---------- | --------- | ------------------------------------------------------------------------------------ |
| **double** | lat       | The location of the place                                                            |
| **double** | lon       | The location of the place                                                            |
| **String** | caption   | An optional caption of the place, shown in bold                                      |
| **String** | detail    | The detail of the place. Use \n to split lines. Cannot be null                       |
| **int**    | backColor | The item's background color. Alpha defaults to 255 if not specified                  |
| **int**    | capColor  | The item caption's color. Alpha defaults to 255 if not specified                     |
| **int**    | detColor  | The item details' color. Alpha defaults to 255 if not specified                      |
| **int**    | pinColor  | The item pin's color. Alpha defaults to 255 if not specified                         |
| **int**    | fontPerc  | The percentage of the font based on the device's original font size. Defaults to 100 |

#### Methods

| Return   | Name                       | Description |
| -------- | -------------------------- | ----------- |
| **void** | serialize(StringBuffer sb) |             |

### Shape

#### Attributes

| Type          | Name   | Description                                            |
| ------------- | ------ | ------------------------------------------------------ |
| **double\[]** | lats   | The coordinates of the polygon                         |
| **double\[]** | lons   | The coordinates of the polygon                         |
| **boolean**   | filled | Set if the item is filled or not                       |
| **int**       | color  | The item color. Alpha defaults to 255 if not specified |

#### Methods

| Return   | Name                       | Description |
| -------- | -------------------------- | ----------- |
| **void** | serialize(StringBuffer sb) |             |

### Circle

#### Attributes

| Type        | Name   | Description                                                                                  |
| ----------- | ------ | -------------------------------------------------------------------------------------------- |
| **double**  | lat    | Center of the circle                                                                         |
| **double**  | lon    | Center of the circle                                                                         |
| **double**  | rad    | The radius; if > 0, its computed as meters; if < 0, its computed as delta of the coordinates |
| **boolean** | filled | Set if the item is filled or not                                                             |
| **int**     | color  | The item color. Alpha defaults to 255 if not specified.                                      |

#### Methods

| Return   | Name                       | Description |
| -------- | -------------------------- | ----------- |
| **void** | serialize(StringBuffer sb) |             |

## **References**

* See the [Java Docs](https://rs.totalcross.com/doc/totalcross/map/GoogleMaps.html) for more information.
* Within the **TotalCross SDK**, usually on Disk C, there is a folder called src/main/java/totalcross and there will be a folder named **Map**, containing a **simple sample** on map. Typically the path to this folder is this pattern:

```
C:\Program Files\TotalCross\sdk\src\main\java\totalcross\map
```


# Static Map

The static map is an image captured by the request of a navigation REST API. This code uses the GOF build pattern.

![Image Sample](/files/-LeL3oBQ4M0M7HT4op1L)

### Requirements

#### Dependecy

You need to add in your **pom file** within your **dependencies tag** the dependency:

{% code title="Dependecy " %}

```
<dependencies>
    .
    .
    .
    <dependency>
        <groupId>com.totalcross.utils</groupId>
        <artifactId>tc-utilities</artifactId>
        <version>0.0.1-SNAPSHOT</version>
    </dependency>
    
</dependencies>
```

{% endcode %}

After downloading the dependency it will be necessary to generate the tcz of the dependency so that it is included in the deploy

Find the folder that is located in the dependency, usually is: C:\Users\\**your\_user**\\.m2\repository\com\totalcross\utils\tc-utilities\0.0.1-SNAPSHOT

![](/files/-Ler7XyzuHa5LexKKFId)

To generate tcz execute the command java -cp "% TOTALCROSS 3\_HOME%" / dist / totalcross-sdk.jar tc.Deploy tc-utilities-0.0.1-SNAPSHOT.jar / r YOUR\_TC\_KEY&#x20;

![](/files/-LerIl475Yrmu5dtoeFU)

After tcz is generated, rename the tc-utilities-0.0.1-SNAPSHOT.tcz file to tc-utilities-0.0.1-SNAPSHOTLib.tcz and place it at the root of the project.

At the root of the project create the file named all.pkg and put \[L] tc-utilities-0.0.1-SNAPSHOTLib.tcz so that this class is included in deploy

![](/files/-LerEHwNAfZIsaPx7r-N)

#### KEY

in the example below, the class was made considering the [**API HERE**](https://developer.here.com/), to get an **APP ID** and **APP CODE** you have to register on the site and create a project, going into the details of the project you will find this information.

{% hint style="info" %}
The 3 points are only to represent in a more playful way that there are other dependencies
{% endhint %}

### Static Map Structures

&#x20;in the example below the class was made considering the [**API HERE**](https://developer.here.com/)

Create in **util** package a new class **StaticMap**

{% code title="Structures" %}

```
└── src
    └── main
        └── java
            └── com.your_company_name.your_name_app
                .
                .
                .
                └── util
                    └── StaticMap
                
```

{% endcode %}

{% hint style="info" %}
The 3 points are only to represent in a more playful way that there are other package.
{% endhint %}

### Static Map Code

{% code title="StaticMap" %}

```java
package <YOUR_PACKAGE_HERE>; // com.your_company_name.your_name_app.util;

import com.tc.utils.utilities.io.HttpConn;
import com.tc.utils.utilities.io.HttpMethod;
import totalcross.io.ByteArrayStream;
import totalcross.io.IOException;
import totalcross.io.Stream;
import totalcross.sys.Convert;
import totalcross.ui.image.Image;
import totalcross.ui.image.ImageException;

public class StaticMap {

    private String appID;
    private String codeID;
    private String andress;
    private int width;
    private int height;
    private int zoom;
    private int format;
    private boolean showMapHeader;
    private String mapStyle;
    private double latitude = Integer.MAX_VALUE;
    private double logitude = Integer.MAX_VALUE;


    public static final int PNG_FORMAT = 0;
    public static final int JPEG_FORMAT = 1;
    public static final int GIF_FORMAT = 2;
    public static final int BMP_FORMAT = 3;
    public static final int PNG8_FORMAT = 4;
    public static final int SVG_FORMAT = 5;

    public static final String ALPS_STYLE = "alps";
    public static final String DREAMWORKS_STYLE = "dreamworks";
    public static final String FLAME_STYLE = "flame";
    public static final String FLEET_STYLE = "fleet";
    public static final String MINI_STYLE = "mini";


    public StaticMap(){
        andress = "";
        latitude = logitude = Integer.MAX_VALUE;
        width = 300;
        height = 300;
        zoom = 14;
        format = PNG_FORMAT;
        showMapHeader = false;
        mapStyle = ALPS_Style;
    }

    public StaticMap(String appID, String codeID){
        this();
        this.appID = appID;
        this.codeID = codeID;
    }



    public Image getImage() {
        Image img = null;

        String req = "https://image.maps.api.here.com/mia/1.6/mapview";
        req += "?app_id=" + appID;
        req += "&app_code=" + codeID;
        if (andress.isEmpty()){
            req += (logitude != Integer.MAX_VALUE && latitude != Integer.MAX_VALUE) ? "&c=" + latitude + "," + logitude : "";
        }else{
            req += "&ci=" + Convert.removeAccentuation(andress).replace("  ", " ").replace(' ', '+');
        }
        req += "&h=" + height;
        req += "&w=" + width;
        req += "&z=" + zoom;
        req += "&f=" + format;
        req += "&i=" + showMapHeader;
        req += "&style=" + mapStyle;

        try {

            HttpConn conn = new HttpConn(req);
            conn.setHttpMethod(HttpMethod.GET);
            Stream stream = conn.connect();

            if (conn.getResponseCode() == 200) {

                byte[] buff = new byte[1024];

                ByteArrayStream bas = new ByteArrayStream(8192);

                while (true) {
                    int n = stream.readBytes(buff, 0, buff.length);
                    if (n <= 0) {
                        break;
                    }
                    bas.writeBytes(buff, 0, n);
                }
                img = new Image(bas.getBuffer());
            }
        } catch (IOException e) {
            e.printStackTrace();
        } catch (ImageException e) {
            e.printStackTrace();
        }
        return img;
    }


    public static class Builder {

        StaticMap staticMap = new StaticMap();

        public Builder(){}

        public Builder(String appID, String codeID) {
            staticMap.appID = appID;
            staticMap.codeID = codeID;
        }

        public StaticMap.Builder setAppID(String appID){
            staticMap.appID = appID;
            return this;
        }

        public StaticMap.Builder setCodeID(String codeID){
            staticMap.codeID = codeID;
            return this;
        }

        public StaticMap.Builder setAdress(String location){
            staticMap.andress = location;
            return this;
        }

        public StaticMap.Builder setHeight(int height){
            staticMap.height = height;
            return this;
        }

        public StaticMap.Builder setWidth(int width){
            staticMap.width = width;
            return this;
        }


        public StaticMap.Builder setZoom(int zoom){
            staticMap.zoom = zoom;
            return this;
        }

        public StaticMap.Builder setFormat(int format){
            staticMap.format = format;
            return this;
        }

        public StaticMap.Builder setShowMapHeader(boolean showMapHeader){
            staticMap.showMapHeader = showMapHeader;
            return this;
        }

        public StaticMap.Builder setMapStyle(String mapStyle){
            staticMap.mapStyle = mapStyle;
            return this;
        }
        public StaticMap.Builder setLocation(double latitude, double logitude){
            staticMap.latitude = latitude;
            staticMap.logitude = logitude;
            return this;
        }

        public StaticMap build(){
            return staticMap;
        }

    }

}
```

{% endcode %}

####

| Atributes         | Description                                                                                                                                                                                                 |
| ----------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| String AppID      | [Key provided by API to identify APP](https://app.gitbook.com/@totalcross/s/playbook/~/drafts/-LeKp9rBA6-LbNYmHT6E/primary/apis/maps/static-map#key)                                                        |
| String CodeID     | [Key provided by API to identify APP](https://app.gitbook.com/@totalcross/s/playbook/~/drafts/-LeKp9rBA6-LbNYmHT6E/primary/apis/maps/static-map#key)                                                        |
| String adress     | It receives an address, as in the example: "Av. Washington Soares, 1321 - Edson Queiroz, Fortaleza - CE, 60811-905"                                                                                         |
| double latitude   | it receives a latitude                                                                                                                                                                                      |
| double logitude   | it receives a latitude                                                                                                                                                                                      |
| int width         | Image width                                                                                                                                                                                                 |
| int height        | Image height                                                                                                                                                                                                |
| int zoom          | The zoom that is applied in the map photo, going from zero (Vision farther) to 21, where 21 will give the view of the whole state and between 0 to 21 it is possible to adjust how close the image is seen. |
| int format        | Indicates the format of the image received                                                                                                                                                                  |
| Boolean mapHeader | Remove or place the map header                                                                                                                                                                              |
| String mapStyle   | Changes the map style received in the image                                                                                                                                                                 |

### How to use

Within the InitUi (), you can declare an image and receive its instance by calling the StaticMap getImage method

{% code title="Sample using StaticMap" %}

```java
public class Maps extends MainWindow {

    public Maps(){
        setUIStyle(Settings.Material);
    }

    @Override
    public void initUI() {
        // Cristo Redentor = -22.951916, -43.2126759;

        double lat = -22.951916;
        double log = -43.2126759;

        int gap = UnitsConverter.toPixels(Control.DP + 16);

        Label lblContact = new Label("Contact");
        lblContact.setForeColor(0x4286f4);
        lblContact.setFont(Font.getFont(false,28));
        add(lblContact, CENTER, TOP + UnitsConverter.toPixels(DP + 50));

        Label lblName = new Label("Christ the Redeemer:");
        lblName.setFont(Font.getFont(false,20));
        add(lblName, LEFT + gap, AFTER + UnitsConverter.toPixels(DP + 20));

        Label lblAdress = new Label("National Park of Tijuca - Alto da Boa Vista, Rio de Janeiro - RJ");
        lblAdress.setFont(Font.getFont(false,14));
        lblAdress.autoSplit = true;
        add(lblAdress, LEFT + gap, AFTER + UnitsConverter.toPixels(DP + 20));

        StaticMap staticMap = new StaticMap.Builder("Fola4mnv4rVDbjzo3Obu", "6Xgu6eVAmLKOPLZXZgy5-Q")
                .setLocation(lat,log)
                .setWidth(Settings.screenWidth - 2 * gap)
                .setHeight(Settings.screenHeight / 3)
                .setZoom(17)
                .build();

        ImageControl imgC = new ImageControl(staticMap.getImage())  ;
        add(imgC, LEFT + gap, AFTER + UnitsConverter.toPixels(DP + 10));

        Button btn = new Button("Navegate");
        btn.addPressListener(e -> {
            String vsEndereco = "geo:"+ lat + "," + log + "?q=" + lat + "," + log;
            Vm.exec("url", vsEndereco,  0, true);
        });
        btn.setFont(Font.getFont(false,18));
        add(btn, CENTER, AFTER + UnitsConverter.toPixels(DP + 30));

    }
}
```

{% endcode %}

![](/files/-LfLPmVhJExxi7Pi1iIV)

## References

See this link for more information abount [GOF patterns](http://www.w3sdesign.com/).


# Material Design Standards

We'll be passing through changes to the base Material Design looks. All of the changes will be listed below.

* [x] Buttons

  * Completely renovated design.
  * Left, right, top, bottom and icon paddings will be added, having their preferred values in Material standards, but also made possible to change by just changing the Button fields: paddingLeft, paddingRight, paddingTop, paddingBottom, and iconPadding.
  * The button will be which one you want from Material Design much more easily, like "Contained Button", "Contained Button with icon", "Outlined Button" and "Text Button".

  **Remember:** You'll always be able to modify all of these values the way you desire.
* [ ] &#x20;Check
  * Insets and text gap will be added, having their preferred values in Material standards.

    **Remember:** You'll always be able to modify all of these values the way you desire.
* [ ] &#x20;ComboBox
  * Completely renovated design.
  * Left, right, top and bottom paddings and icon gap will be added, having their preferred values in Material standards, but it is also possible to change them via public attributes.
  * The arrow color, margin, and size will change.
  * The ListBox used to show the options of the ComboBox component will also follow the Material standards.

    **Remember:** You'll always be able to modify all of these values the way you desire.
* [ ] \[X] ListBox
  * Some design adjustments.
  * Left, right, top and bottom paddings will be added, having their preferred values in Material standards.
  * You'll be able to add a right icon now, having a left and right icon at the same time, if you want to. (Previously, you only could add a left icon)
  * You'll be able to control the gap between the icon and the item text.
  * The ListBox used on a DropDown context (like on a ComboBox) will follow its Material standards, which is different when it's used as a simple list.

    **Remember:** You'll always be able to modify all of these values the way you desire.
* [x] Edit
  * Some design adjustments.
  * **OutlinedEdit** added, having the preferred values in Material standards, but made possible to change via public atributes and methods.
* [ ] Grid
* [ ] ListContainer
* [x] MaterialWindow
* [ ] \[X] MessageBox
  * Completely renovated design.
  * Left, right, top and bottom paddings added, having their preferred values in Material standards, but it is also possible to change them via public attributes.
  * Public gap values between internal elements, so you can change it the way you want.
  * Public text fonts, so you can customize it the way you desire.
  * Here are some images, so you can get the preview:

    ![messagebox\_nobuttons](/files/-LvMlX0pVIcujEOLU4XE)

    ![messagebox\_twobuttons](/files/-LvMl_-8WOA90szsruwv)

    ![messagebox\_twobuttons\_big](/files/-LvMlbploIOckKwA4-dy)
* [ ] MultiEdit
* [x] ProgressBar
  * Completely renovated design.
  * Now you can change the filled bar size when it's an endless bar.
  * Now when the filled bar reaches the end of the progress bar, it gradually starts appearing at the beginning of the progress bar when the bar is endless.
* [ ] \[X] ProgressBox
  * Completely renovated design.
  * Now the endless bar starts gradually at the beginning while the bar reaches the end of the progress bar.
  * Here are some images, so you can get the preview:

    ![progressbar\_endless\_notext](/files/-LvMlehPlBmXjl_qpcOr)

    ![progressbar\_endless\_text](/files/-LvMlhZEXux6ixNrUCYt)
* [x] PopupMenu
  * Completely renovated design
  * Now you can popup this anywhere you want by using popupAt(int x, int y). This can be pretty useful when you want to show some quick options.
  * Now you can change the size of its bounds.
  * Now you can get the ListBox (which is the menu) and change its paddings.
* [ ] PushButtonGroup
* [x] RadioButton
* [x] SideMenu
* [ ] \[X] Slider
  * Small adjusts to follow Material Design standards.
  * Now the ticks are drawn behind the slider circle, not above.
  * Now you can choose the ticks color independently with the ticksColor attribute.
  * Now you can choose the bar height with the barHeight attribute.
  * Here are some images, so you can get the preview:

    ![slider\_hor](/files/-LvMm9z8DSzmRxt_SEmb)

    ![slider\_ver](/files/-LvMmCj9jW72fSmUl367)
* [ ] \[X] Switch
  * Small adjusts to follow Material Design standards.
* [ ] TabbedContainer
* [ ] \[X] Toast
  * Completely renovated design.
  * Now you can add a button to it that will be shown at the right, so you can add events to it to do whatever you desire.
  * A bug where the Toast faded out immediately after called is now fixed.
  * Here are some images, so you can get the preview:

    ![single\_line\_toast](/files/-LvMlweUABy3cfsiMO_C)

    ![double\_line\_button\_toast](/files/-LvMlyvHV2Moij48EH1L)

    ![double\_line\_big\_button\_toast](/files/-LvMm0f2zc2XAmP589q_)
* [ ] Tooltip
* [ ] TopMenu

This page will be updated constantly.


# Ninepath

## Overview

NinePatch is a class that allows you to create nine custom patches that will be sized the way you define them. It draws an extensible image so you can resize it without losing the edges.

The amount of designs that can be created using this technique is virtually endless, so much so that Android also uses this tool.

To adjust the images and create the guides, keeping in mind that the corners will stay fixed, you need the help of a designer or someone with knowledge in image editing tools as illustrator.

But there are also sites that help to perform this work in a [simpler way as this site](https://romannurik.github.io/AndroidAssetStudio/nine-patches.html#source.type=image\&sourceDensity=480\&name=multibutton). In it, just upload the desired image and then adjust the guides (always keeping in mind that the corners are fixed). That done, just download the .zip file containing the guides!

## Methods

| Type          | Name                                                                                                                                         | Description                                                                                                                                                                                                                            |
| ------------- | -------------------------------------------------------------------------------------------------------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| **NinePatch** | getInstance( )                                                                                                                               | Returns the instance of the NinePatch                                                                                                                                                                                                  |
| **Parts**     | load(Image)                                                                                                                                  | Return the 9 ninepatch parts from a Image with the guides                                                                                                                                                                              |
| **Parts**     | <p>load(Image original, int scalableAreaStartWidth,<br>int scalableAreaEndWidth, int scalableAreaStartHeight, int scalableAreaEndHeight)</p> | Returns the 9 ninepatch parts of the image without the guides but with the values of the points that will cut the image                                                                                                                |
| **Parts**     | load(Image original, int scalableAreaWidth, int scalableAreaHeight)                                                                          | Returns the 9 parts of the ninepatch of a image without the guides but with the values that are going to be used for the borders rectangles, that are the respective width and height. All border rectangles are equals in this case.  |
| **Image**     | getNormalInstance(Parts p, int width, int height, int color, boolean rotate)                                                                 | Return the result image built from the given width and height; If the given color is different from -1, it will apply the rgb colors in every pixel from the image. If the given boolean is true, the image will be rotated 180º.      |
| **Image**     | getNormalInstance(int type, int width, int height, int color, boolean rotate)                                                                | Return the result image from one of Totalcross standard ninepatchs. If the given color is different from -1, it will apply the rgb colors in every pixel from the image. If the given boolean is true, the image will be rotated 180º. |
| **Image**     | getPressedInstance(Image img, int backColor, int pressColor)                                                                                 | Return the given image with a pressed effect from the given color                                                                                                                                                                      |
| **void**      | tryDrawImage(Graphics g, Image npback, int x, int y)                                                                                         | Draws on the given Graphics the given image on the x and y coordinates.                                                                                                                                                                |


# Notifications

Notification is a message that will be displayed to the user outside of the application’s usual UI.

When you execute a command telling the system to issue a notification, it will appear as an icon in the notification area, and to see the details, the user opens the **notification space**.

{% hint style="info" %}
The notification space is this area where the details are shown (also called the notification drawer) are areas controlled by the system and the user can see at any time.
{% endhint %}

### Creation of a Notification

* To specify actions and information that will be displayed to the user, use a `Notification.Builder` object.

* To create a push notification, use `Notification.Builder.build()`, which is an example of the type of `notification` provided as previously defined specifications.

* To notify a notification, simply pass the `Notification` object using `NotificationManager.getInstance().Notify();`

### Content Needed to Create a Notification

The object on smartphones should contain the following:

* A title, defined by `title();`
* Detail text, defined by `text();`

### A Simple Example

{% code title="HelloTCNotification" %}

```java
import totalcross.notification.Notification;
import totalcross.notification.NotificationManager;
import totalcross.sys.Settings;
import totalcross.ui.Button;
import totalcross.ui.Edit;
import totalcross.ui.MainWindow;

public class HelloWorld extends MainWindow {
	private Button btnHello;

	public HelloWorld(){
		super("", NO_BORDER);
		Settings.uiAdjustmentsBasedOnFontHeight = true;
		setUIStyle(Settings.Material);
	}

	public void initUI() {
		Edit title = new Edit("Title");
		title.caption = "Title";
		add(title, LEFT+150, TOP+100, FILL-150, PREFERRED);
		
		Edit text = new Edit("Text");
		text.caption = "Text";
		add(text, LEFT+150, AFTER+50, FILL-150, PREFERRED);
		
		btnHello = new Button("Notify!");
		btnHello.addPressListener(
				(e) -> {
					Notification.Builder builder = new Notification.Builder();
					Notification notification = builder
							.title(title.getText())
							.text(text.getText())
							.build();
					NotificationManager.getInstance().notify(notification);
				});
		add(btnHello, CENTER, AFTER+150, PARENTSIZE+38, PARENTSIZE+8);
	  }
}
```

{% endcode %}

### References

* to see the complete example, go to our [GitHub](https://github.com/TotalCross/Notifications)
* You can also view this [quick tutorial video](https://www.youtube.com/watch?v=Y1_0c9H8G4E) on how to create notifications.


# PrinterManager

## Overview

PrinterManager is the class responsible for enabling printing on Cielo machines and it uses the singleton pattern to guarantee a unique instance of PrinterManager.&#x20;

## Atributes

The attributes will be inserted into the hashMap and will be used at the time of printing

#### Used in alignment - KEY\_ALIGN

| Name               | Description     |
| ------------------ | --------------- |
| VAL\_ALIGN\_CENTER | Align to center |
| VAL\_ALIGN\_LEFT   | Align to left   |
| VAL\_ALIGN\_RIGHT  | Align to right  |

#### Other features

| Name                | Description                                                                                             |
| ------------------- | ------------------------------------------------------------------------------------------------------- |
| KEY\_TEXT\_SIZE     | Text size, must be an integer value                                                                     |
| KEY\_TYPEFACE       | Text font, must be an integer between 0 and 8, where each value is a&#xD; different font                |
| KEY\_MARGIN\_LEFT   | Left margin, must be an integer value                                                                   |
| KEY\_MARGIN\_RIGHT  | Right margin, must be an integer value                                                                  |
| KEY\_MARGIN\_TOP    | Top margin, must be an integer value                                                                    |
| KEY\_MARGIN\_BOTTOM | Bottom margin, must be an integer value                                                                 |
| KEY\_LINE\_SPACE    | Spacing between consecutive lines, must be an integer value                                             |
| KEY\_WEIGHT         | Used when printing multiple columns, to choose the weight of each column,&#xD; must be an integer value |

## Methods

| Name                                                                                                                                                       | Description                                                                                                                                                                                                         |
| ---------------------------------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| getInstance()                                                                                                                                              | Creates a new instance or returns the instance previously created.                                                                                                                                                  |
| <p>printText(String textToPrint, Map\<String, Integer> printerAttributes)<br></p><p>printText(String textToPrint, Map\<String, Integer> printerAttributes, |                                                                                                                                                                                                                     |
| PrinterListener printerListener)</p>                                                                                                                       | <p>Prints the text received in the textToPrint parameter.</p><p></p><p>printerAttributes will have the attributes of the print.</p><p></p><p>printerListener will receive the PrinterListener interface methods</p> |

## Usage

{% code title="Code Example" %}

```java
HashMap<String, Integer> printerAttributes = new HashMap<>();

printerAttributes.put(PrinterAttributes.KEY_ALIGN, PrinterAttributes.VAL_ALIGN_CENTER);
printerAttributes.put(PrinterAttributes.KEY_TYPEFACE, 1);
printerAttributes.put(PrinterAttributes.KEY_TEXT_SIZE, 20);

String textToPrint = "TEXT TO PRINT";
PrinterManager.getInstance()
               .printText(textToPrint, printerAttributes);
```

{% endcode %}


# Push Notification Firebase

We can judge as notifications as and in some cases with the same irritant. But even so, dates remain one of the most efficient ways to interact with your users and ensure their return to your application.

You can use Firebase as a basis to send a notification to the user of your mobile application.

## What is Firebase?

[Firebase](https://firebase.google.com/?gclid=Cj0KCQjw4fHkBRDcARIsACV58_GiXRpyAtn5fhmrMzOek0nBNHGtA9H2KEFg05N8C_qKtm2aPU34FGQaAqrsEALw_wcB) is a platform that offers several services for both mobile and web applications. With this technology, you can incrementally add to your app several functions in a simple and fast way.

When it comes to notification, TotalCross uses the service called **Cloud Messaging**.

{% hint style="info" %}
[Firebase Cloud Messaging (FCM)](https://firebase.google.com/docs/cloud-messaging/?hl=en-us) is a message solution between platforms, allowing you to send notifications reliably and cost-effectively.
{% endhint %}

Until now, there were no binding to get the Firebase Identitity Token, but **as of TotalCross 3.43 for Android** and **TotalCross 4.1.0 for iOS**, we finally finish these binds!

## Configuring the Environment

### Creating a TotalCross Project.

* Create a **Maven project** called **PushNotification\_Firebase** and configure pom.xml to use TotalCross.

If you **don't know** how to create and configure a Maven project, log in below:

{% content-ref url="/pages/-La1Eu0-urVdB\_j7-nmS" %}
[Broken mention](broken://pages/-La1Eu0-urVdB_j7-nmS)
{% endcontent-ref %}

* Create a package called **pushnotification\_firebase**, and then create a class with the same name. This class will be our **MainWindow**.

![](/files/-LbOV5v6n7f1AdGbe_jP)

Within the PushNotification\_Firebase, create a **static String** named **firebaseToken**. And within the method, we will use the command `FirebaseInstanceId.getInstance().GetToken();` to get the token. In addition, we'll add a message to be printed on the console to show the token. In the end, it will look like this:

{% code title="PushNotification\_Firebase.java" %}

```java
public static String firebaseToken;

	public PushNotification_Firebase() {
		firebaseToken = FirebaseInstanceId.getInstance().getToken();
		System.out.println("FIREBASE TOKEN: " + firebaseToken);
	}
```

{% endcode %}

{% hint style="info" %}
This token is needed to send a unicast message to a single device, or to identify that device so that we can create a group to send messages. So let's start with the basics and then go toward the identification of a single device to send a custom message for it.
{% endhint %}

* Okay, done that, let's create a static block to set the application ID of your application through the `applicationID` attribute. In android this is called **APP Bundle**. With this, our PushNotification\_Firebase class will look like this:

{% code title="PushNotification.java" %}

```java
public class PushNotification_Firebase extends MainWindow {
	public static String firebaseToken;

	public PushNotification_Firebase() {
		firebaseToken = FirebaseInstanceId.getInstance().getToken();
		System.out.println("FIREBASE TOKEN: " + firebaseToken);
	}
	
	static{
		Settings.applicationId = "TCFB";
	}
}
```

{% endcode %}

{% hint style="warning" %}
the chosen Id must always be a string with 4 letters. This id is very important because the name of our Android project should be totalcross.app . Do not worry, let's get better at the next step!&#x20;
{% endhint %}

* Finally, check if your project has a folder named **target**, otherwise, create a folder named target in the same location as the pom.xml, src, and .settings file.

![](/files/-LbUAiuT94mpn9xooY0S)

### Creating a Firebase project

* Go to [Firebase](https://firebase.google.com/) website and click "Go to Console," and then click "Create New Project." Let's call it "Push Notification"

![](/files/-LbTrgHprCQljMcTaMpN)

Then you can click on "Create project" and then "Continue".

You will be redirected to an overview of your project, where you will click on the Android icon that is in the banner of the page, as shown in the image below:

![](/files/-LbU4wu8fx3np0LsV7sz)

* A form will appear for you to fill out. In the first step, Register App, you only need to fill in the name of the Android package. Here you must fill in with **totalcross.app\<Settings.applicationID>**  that you filled in the previous step. In this case, it will be called **totalcross.appTCFB**. You can then click Register App.

![](/files/-LbU4zmsX3fWKCQnkGhp)

* The second step is quite simple, just click to download the file **google-services.json** and then copy the file and paste inside the **target** folder, within your project and then click **next**.

{% hint style="warning" %}
If you are deploying to Android and TotalCross can't find google-servoces.json, it will tell you that Firebase won't work with this message:

"Could not find 'google-services.json', thus Firebase will be ignored further on"
{% endhint %}

![](/files/-LbUBcqCi3LAxjlmj2yW)

* Step 3 is just to Gradle, so we can **click next**
* Step 4 will only be possible when we test, so we can click the "**Skip step**" option.

## Implementation

Now, with the environment set up, we can go back to our `MainWindow`, the PushNotification\_Firebase. Inside it, let's create two more methods: **`onTokenRefresh()`** and **`onMessageReceived()`**.

### Receiving Token

It is through **onTokenRefresh()** that you will be able to receive the Token to later save and associate with a user. Check out the example below:

{% code title="onTokenRefresh()" %}

```java
protected FirebaseInstanceIdService initFirebaseInstanceIdService() {
    return new FirebaseInstanceIdService() {
        @Override
        public void onTokenRefresh() {
            firebaseToken = FirebaseInstanceId.getInstance().getToken();
            System.out.println("Token refresh");
        }
    };
}
```

{% endcode %}

### Receiving Notification

The `onMessageReceived()` method fires every time the APP receives a notification, so to be more illustrative when testing, we will use this method to print to the console which notification was sent. Just copy the code below

{% code title="onMessageReceived()" %}

```java
    protected FirebaseMessagingService initFirebaseMessagingService() {
        return new FirebaseMessagingService() {
            @Override
            public void onMessageReceived(RemoteMessage remoteMessage) {
                Vm.debug("I was called");
                System.out.println((String)remoteMessage.getData().get("hello"));
            }
        };
    }
```

{% endcode %}

### Reviewing PushNotification\_Firebase class (extends MainWindow)

And finally, your main class must to be as follows:

{% code title="PushNotification\_Firebase" %}

```java
package pushnotification_firebase;

import totalcross.firebase.FirebaseMessagingService;
import totalcross.firebase.RemoteMessage;
import totalcross.firebase.iid.FirebaseInstanceId;
import totalcross.firebase.iid.FirebaseInstanceIdService;
import totalcross.sys.Settings;
import totalcross.sys.Vm;
import totalcross.ui.MainWindow;

public class PushNotification_Firebase extends MainWindow {
	public static String firebaseToken;

	public PushNotification_Firebase() {
		firebaseToken = FirebaseInstanceId.getInstance().getToken();
		System.out.println("FIREBASE TOKEN: " + firebaseToken);
	}
	
	static{
		Settings.applicationId = "TCFB";
		Settings.iosCFBundleIdentifier = "totalcross.appABCD";
	}

	@Override
	protected FirebaseInstanceIdService initFirebaseInstanceIdService() {
		return new FirebaseInstanceIdService() {
			@Override
			public void onTokenRefresh() {
				firebaseToken = FirebaseInstanceId.getInstance().getToken();
				System.out.println("Token refresh");
			}
		};
	}

	@Override
	protected FirebaseMessagingService initFirebaseMessagingService() {
		return new FirebaseMessagingService() {
			@Override
			public void onMessageReceived(RemoteMessage remoteMessage) {
				Vm.debug("I was called");
				System.out.println((String) remoteMessage.getData().get("hello"));
			}
		};
	}
}
```

{% endcode %}

You are ready to send a first message. The ideal is always first, so keep learning how to submit an application!.

## Test

![](/files/-LaueYXyzaLOXR1oKqBy)

## References

* You can check the complete example in the [GitHub](https://github.com/TotalCross/PushNotification_Firebase).
* It is also possible to send internal notifications from your app to users. To better understand how this is possible, access the notification session (link below).

{% content-ref url="/pages/-Lb42QJ6x7K81Nr5yl6g" %}
[Notifications](/master/documentation/apis/notifications)
{% endcontent-ref %}


# Scanner

## Overview

Are you thinking in implements a barcode reader in your app? TotalCross have a simple solution. It is easy to make a Scanner application and there is an example ready to use on GitHub!

## Methods

| Name                     | Description                |
| ------------------------ | -------------------------- |
| readBarcode(String mode) | <p>The mode can be one of: |

</p><p>    1D - for one dimension barcodes</p><p>    2D - for QR codes</p><p>    empty string - for both<br></p><p>The parameter &#x26;msg:</p><p>You can show a message in display</p> |

## How to use

There are two ways to make the scanner.

### With Scandit:

&#x20;When we do a Scanner.readBarcode and we set on parameter characters "scandit:" with a String contains the scandit key and the camera be call and will capture the image and set on the label result. You will use like this:

&#x20;`scan = Scanner.readBarcode("scandit:" + YOUR_SCANDIT_KEY);`

### With ZXing:

In here, we have a little more work because we need find the barcode's mode, if is a 1D or 2D and just after that, we can write Scanner.readBarcode and set the mode and a message telling the user how scanner the barcode.

`scan = Scanner.readBarcode("mode=" + mode + "&msg=" + msg);`

## References

* See more in [Javadoc](https://rs.totalcross.com/doc/totalcross/io/device/scanner/package-summary.html)
* See a project using scanner on [github](https://github.com/TotalCross/ScanditSample)


# SOAP

## Overview

> “SOAP Version 1.2 (SOAP) is a lightweight protocol intended for exchanging structured information in a decentralized, distributed environment. It uses XML technologies to define an extensible messaging framework providing a message construct that can be exchanged over a variety of underlying protocols. The framework has been designed to be independent of any particular programming model and other implementation specific semantics.” - Definition from SOAP Version 1.2 Part 1: Messaging Framework (Second Edition) - W3C Recommendation 27 April 2007

Because of its implementation independence, the SOAP protocol is widely used on the implementation of Web Services.

## The SOAP Class

This class represents a SOAP message that, when executed, is sent to the server in a HTTP request. The server response is then received, processed, and the answer made available.

Before creating a instance of **SOAP**, you may set the following class fields:

* The prefix string used to start the request. Note that it uses UTF-8, so unicode characters are not supported. Its default value is:

```markup
<?xml version="1.0" encoding="UTF-8"?>
<soapenv:Envelope xmlns:soapenv="
http://schemas.xmlsoap.org/soap/envelope/"
xmlns:xsd="http://www.w3.org/2001/XMLSchema"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<soapenv:Body>
```

* suffix The suffix string used to finish the request. Its default value is:

```markup
</soapenv:Body>
</soapenv:Envelope>
```

debug Changing this value to true enables debug mode, which writes XML parsing information on the debug console (or the default error output when running on JDK). You may also set HttpStream.debugHeader = true.\
Caution: don’t use this on device because it increases a lot the memory usage.

disableEncoding The SOAP request will ask the server for GZip or ZLib encoded response by default. To disable encoding, **set this field to true**.

## Constructors

&#x20;To create a new **SOAP** instance, you must use the following constructor:

| Type            | Name                         | Description                                                                                                                                                                                                                                         |
| --------------- | ---------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| **constructor** | SOAP(String mtd, String uri) | Creates a new SOAP request where mtd specifies the remote method to be executed, and uri, the address of the Web Service. The default namespace will be used, along with an open timeout of 25 seconds, and a read and write timeout of 60 seconds. |

## Instance Fields

After creating a new **SOAP** object, you may set some of its following instance fields:

| Type        | Name                 | Description                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                 |
| ----------- | -------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| **boolean** | wasCompressionUsed   | A flag that indicates if the SOAP connection was using either GZip or ZLib. This is a ready-only flag, set during the execute() method, and changing its value has no effect.                                                                                                                                                                                                                                                                                                                               |
| **String**  | alternativeReturnTag | By default, the XML parser used by SOAP will recognize as an answer tag any tags whose name ends with “result” or “return” (ignoring the case). This field, if set, specifies an alternative answer tag name, recognizing any XML element that ends with the specified value as an answer tag. AlternativeReturnTag IS CASE SENSITIVE, unlike the SOAP default tag names. Also, alternativeReturnTag does not replace the default values. It’s just a new value with higher priority over the default ones. |
| **String**  | namespace            | String that identifies the service’s namespace. Its default value is: <http://schemas.xmlsoap.org/soap/>.                                                                                                                                                                                                                                                                                                                                                                                                   |
| **int**     | openTimtout          | Specifies the connection open timeout value in milliseconds. Its default value is defined by the constant DEFAULT\_OPEN\_TIMEOUT (25 s).                                                                                                                                                                                                                                                                                                                                                                    |
| **int**     | readTimeout          | Specifies the connection read timeout value in milliseconds. Its default value is defined by the constant DEFAULT\_READ\_TIMEOUT (60 s).                                                                                                                                                                                                                                                                                                                                                                    |
| **int**     | writeTimeout         | Specifies the connection write timeout value in milliseconds. Its default value is defined by the constant DEFAULT\_WRITE\_TIMEOUT (60 s).                                                                                                                                                                                                                                                                                                                                                                  |
| **String**  | mtd                  | Stores the name of the remote method.                                                                                                                                                                                                                                                                                                                                                                                                                                                                       |
| **String**  | uri                  | Stores the address to the Web Service.                                                                                                                                                                                                                                                                                                                                                                                                                                                                      |

You may change both the **mtd** and the **uri** values before executing the request. Although this seems to be pointless, because these values are passed to the constructor.

If the remote method expects any arguments, you must set them using the **`setParam()`** method. However, there are several versions of this method to cover different argument types. Listing all of them would be pointless, so we’ll define a generic type that we’ll refer as , and may be one of the of the following:

* int<br>
* boolean<br>
* double<br>
* String<br>

So, whenever a SOAP method is described like **`setParam( param)`**, you can safely assume there are four versions of this method, one for each type listed above. Other type of parameters can be passed using similar methods. Unicode characters are not accepted because the default header uses UTF-8.

## SOAP methods for parameters setting:

| Type     | Name                                                                           | Description                                                                                                         |
| -------- | ------------------------------------------------------------------------------ | ------------------------------------------------------------------------------------------------------------------- |
| **void** | setParam( param)                                                               | Sets the given value in the method’s argument order.                                                                |
| **void** | setParam(\[] param)                                                            | Sets the given array in the method’s argument order.                                                                |
| **void** | setParam( param, String paramName)                                             | Sets the given value, identifying it with the given parameter name.                                                 |
| **void** | setParam(\[] param, String paramName)                                          | Sets the given array value, identifying it with the given parameter name.                                           |
| **void** | setParam(byte\[] param, String paramName)                                      | Sets a byte array value, identifying it with the given parameter name.                                              |
| **void** | setParam(String param, String paramName, String paramType)                     | Sets a String parameter in the method, identifying it with the given name and specifying its type as the given one. |
| **void** | setParam(String\[] param, String paramName, String paramType)                  | Sets a String array value, identifying it with the given parameter name and specifying its type as the given one.   |
| **void** | setObjectParam(String paramName,String\[] fieldNames, String\[] fieldValues)   | Sets an Object parameter value, by specifying its parameter name, field names and field values.                     |
| **void** | setObjectArrayParam(String paramName,String\[] fieldNames, Vector fieldValues) | Sets an Object array parameter value, by specifying its parameter name, field names and field values.               |

The only thing left to do now is to execute the request and check the service’s answer:

| Type       | Name                                                                 | Description                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                              |
| ---------- | -------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
| **void**   | execute( )                                                           | This method simply executes the prepared SOAP request.                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                   |
| **Object** | getAnswer( )                                                         | To retrieve the method’s answer, you must call this method after execute(). The return type of this method is Object, but it may return only three different values (the values may be escaped; use totalcross.ui.html.EscapeHtml.unescape() to convert it back). The remote method return type is known, so you may just typecast the Object returned by getAnswer() to String or String array, converting its values if necessary. The possible returns are: 1- null When the remote method has no return value or the execution failed for any reason. 2- String When the remote method returns a single value. If the expected value is not String, you must convert the received String to the right type (e.g. if you’re expecting an int value, you can use Convert.toInt()). 3- String\[] When the remote method returns an array or an Object. If the expected value is not a String array, you must convert each value of the array to the right type. If it’s an object, the array contains its field values. |
| **void**   | useProxy(String address, int port, String username, String password) | Sets the proxy settings to be used by the SOAP connection. You may optionally set the username and password for basic proxy authorization. Proxy authorization is disabled if either username or password is null. In this method, address is the proxy address port and port is the proxy port.                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                         |

## References

* For more details, check out the **totalcross.xml.soap** package [JavaDocs](https://rs.totalcross.com/doc/).


# Socket

## Overview

The **Socket** class allows you to open TCP/IP connections from your device. To be able to establish a connection with a particular server, both the server and the device must be connected to a common network (e.g. a local network that connects your computers and devices, or the Internet).

A **Socket** object denotes a client-server connection over a network using the TCP/IP protocol, where the device acts as a client, which connects to a specific server port.

The **Socket** class does not provide many methods besides the ones inherited from **Stream**. After creating a socket, you’ll usually just perform read and write operations, closing the socket after you’re done.

However, streams that handle remote connections are more likely to fail due to hardware and communication problems, so we shouldn’t handle socket operations the same way we do with file operations.

In TotalCross, socket’s read and write operations are blocking with a timeout – that means that socket methods will block the thread until the operation is completed, or the timeout for the operation is reached. If the operation is completed, the method returns immediately, regardless of the amount of time left. Otherwise, the method will just return the amount of data processed.

It’s important to notice that no exception is thrown if the method times out. This is just a way to prevent your thread from being blocked indefinitely because of communication problems. You may just keep executing the same method until it finishes processing all the data.

## **Constructors**

| Type            | Name                                                         | Description                                                                                                                                                                                                                                                                                                                                                                                                                |
| --------------- | ------------------------------------------------------------ | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| **constructor** | Socket(String host, int port, int timeout, boolean noLinger) | Creates a new socket that attempts to establish a connection by looking up the given host and performing the 3 way TCP/IP handshake. The argument port specifies the server port to connect to, while timeout specifies the timeout for this operation in milliseconds. The argument noLinger indicates if a socket upon close should shutdown the connection immediately or check for any server response before closing. |
| **constructor** | Socket(String host, int port, int timeout)                   | Same as the above, but uses the default value false for the argument noLinger.                                                                                                                                                                                                                                                                                                                                             |
| **constructor** | Socket(String host, int port)                                | Same as the above, but uses the default value 1500 (milliseconds) for the argument timeout.                                                                                                                                                                                                                                                                                                                                |
| **constructor** | Socket(String host, int port, int timeout, String params)    | Opens a socket with additional parameters. Each parameter is specified in a key=value form and separated by a ; from the next parameter. For example: p1=v1;p2=v2. If true, the socket is closed immediately, and no ack is waited from the server. Note that this must be done for the very first socket creation per application.                                                                                        |

You cannot open a socket before the main event loop. In other words, you cannot open a socket in the app’s constructor, but you can in the **initUI( )** method.

The socket general behavior, including the timeout for read and write operations, are stored in the following public fields:

* **`readTimeout`** - The timeout value for read operations. Its default value is Socket. `DEFAULT_READ_TIMEOUT`.<br>
* **`writeTimeout`** - The timeout value for write operations. Its default value is Socket. `DEFAULT_WRITE_TIMEOUT`.

Usually you should not worry about the read and write timeouts. The default values will be fine in most cases. However, you may increase the timeout value if you experience problems with slow connections.

Reducing the timeout value is usually a bad idea. If your device has a high speed connection, the read and write methods should also be fast and return before the timeout is reached. However, reducing the timeout value won’t give you any benefit, and may even decrease your program performance.

Methods for read and write operations:

## Methods:

| Type       | Name                    | Description                                                                                                                                                                               |
| ---------- | ----------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| **int**    | readBytes(byte\[] buf)  | Attempts to read enough bytes from this socket to fill the given buffer.                                                                                                                  |
| **String** | readLine( )             | Attempts to read a line of text from this socket. A line is a sequence of characters delimited by any character lower than blank. This method correctly handles newlines with \n or \r\n. |
| **int**    | writeBytes(byte\[] buf) | Attempts to write the contents of the given buffer to this socket.                                                                                                                        |
| **int**    | writeBytes(String s)    | Attempts to write the given string to this socket.                                                                                                                                        |

Except for the method **readLine( )**, the methods above are just available for convenience and may be replaced by read/write calls inherited from **Stream**. This has a cost however - using these methods increases the number of method calls for each read/write operation by one (they actually just call the **Stream** methods). If your application makes heavy use of sockets, you may avoid using these methods to improve its performance.

## References

* For more details, check out **totalcross.net.Socket** [JavaDoc](https://rs.totalcross.com/doc/).


# SocketServer

## Overview

This class implements server sockets. A server socket waits for requests to come in over the network. It may then accept the incoming TCP/IP connection and perform some operation based on that request, possibly returning a result to the requester.

**ServerSocket** constructors:

## Constructors

| Type            | Name                                                          | Description                                                                                                                                                                                                                                                                                                             |
| --------------- | ------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| **constructor** | ServerSocket(int port)                                        | Attempts to open a server socket at the specified port number. By default, the maximum number of simultaneous connections allowed is DEFAULT\_BACKLOG and the default timeout for accept is DEFAULT\_SOTIMEOUT, and the server is not bound to any specific local address. The port number must be between 0 and 65535. |
| **constructor** | ServerSocket(int port, int timeout)                           | Same as the above, but you may also specify the timeout value, in milliseconds, for the accept operation. This value must be a positive value, or 0 to wait forever.                                                                                                                                                    |
| **constructor** | ServerSocket(int port, int timeout, String addr)              | Same as the above, but you may also specify a local address, which the server should bind to. If the argument addr has a null value, it is ignored and the server is not bind to any address.                                                                                                                           |
| **constructor** | ServerSocket(int port, int timeout, int backlog, String addr) | Same as the above, but you may also specify the maximum number of simultaneous connections allowed with the argument backlog, which must have a positive value.                                                                                                                                                         |

You may retrieve the address and port values of this **ServerSocket** with **`getHost()`** and **`getLocalPort( )`**.

After creating a server socket, you may use the method **`accept()`** to wait for incoming connections. This method blocks the thread for the amount of time specified by the timeout value passed to the constructor, returning a **null** value when the timeout is over, or until a connection request is received and accepted, returning a socket instance representing the new connection.

The returned object is always a valid **Socket** instance, that may be used to transfer data between this server and the client that requested the connection, and that should be closed when no longer needed.

You should never use blocking operations on threads handling events and/or the graphical interface, otherwise the user won’t be able to interact with the application. Take a look at the source code of the sample ServerSocketTest.

Finally, you may use the method **`close()`** to close this server socket, releasing any associated resources.

Remember to close any sockets associated to this server socket before closing it. Otherwise all open sockets will throw an **IOException**.

## References

* For more details, check out **totalcross.net.ServerSocket** [JavaDoc](https://rs.totalcross.com/doc/).


# SQLite Encryption

## Overview

Allows reading and writing encrypted database files. All database content, including the metadata, is encrypted so that to an outside observer the database appears to be white noise.

The following encryption algorithms are currently supported:

* AES-128 in OFB mode (default)
* AES-256 in OFB mode

## **Key Formats**

There are three different key formats. The first format

```java
props.put("key", new Properties.Str("'secret-password'"));
```

takes the key string and repeats it over and over until it exceeds the number of bytes in the key of the underlying algorithm (16 bytes for AES128, 32 bytes for AES256, or 256 bytes for RC4). It then truncates the result to the algorithm key size. The approach limits the key space since it does not allow 0x00 bytes in the key. The second format

```java
props.put("hexkey", new Properties.Str("'secret-password'"));
```

accepts the key as hexadecimal, so any key can be represented. If the provided key is too long it is truncated. If the provided key is too shorted, it is repeated to fill it out to the algorithm key length. The third format

```java
props.put("textkey", new Properties.Str("'secret-password'"));
```

computes a strong hash on the input key material and uses that hash to key the algorithm. The -textkey format is recommended for new applications.

## **Key Material**

The amount of key material actually used by the encryption extension depends on the algorithm. With see-rc4.c, the first 256 byte of key are used. With aes-128, the first 16 bytes of the key are used. With aes-256, the first 32 bytes of key are used.

If you specify a key that is shorter than the maximum key length, then the key material is repeated as many times as necessary to complete the key. If you specify a key that is larger than the maximum key length, then the excess key material is silently ignored. For the

```java
props.put("textkey", new Properties.Str("'secret-password'"));
```

option, up to 256 bytes of the passphrase are hashed using RC4 and the hash value becomes the encryption key. Note that in this context the RC4 algorithm is being used as a hash function, not as a cryptographic function, so the fact that RC4 is a cryptographically weak algorithm is irrelevant.

## **Encryption algorithm selection using a key prefix**

The key may begin with a prefix to specify which algorithm to use. The prefix must be exactly one of "aes128:", or "aes256:". The prefix is not used as part of the key sent into the encryption algorithm. So the real key should begin on the first byte after the prefix. Take note of the following important details:

* The prefix is case sensitive. "aes256:" is a valid prefix but "AES256:" is not.
* If the key prefix is omitted or misspelled, then the encryption algorithm defaults to "aes128" and the misspelled prefix becomes part of the key.
* The algorithm prefix strings work on the "see.c" variant of SEE only. For any of see-aes128-ofb.c, see-aes255-ofb.c or see-aes128-ccm.c any prefix on the key is interpreted as part of the key.
* When using PRAGMA hexkey or PRAGMA hexrekey, the key prefix must be hex encoded just like the rest of the key.

```java
props.put("hexkey", new Properties.Str("'aes128:6d796b6579'"));          // Wrong!!
props.put("hexkey", new Properties.Str("'6165733132383a6d796b6579'"));   // correct
```

### **Limitations**

* TEMP tables are not encrypted.
* In-memory (":memory:") databases are not encrypted.
* Bytes 16 through 23 of the database file contain header information which is not encrypted.
* Encryption is **NOT** supported on the simulator. To be able to use it, you need to remove the encryption. That can be done with a native Totalcross application like the previous example sending a empty value to rekey
* Only supported for Pro or Enterprise users; Applications using old or free keys can´t use encryption.

## **Usage**

In the following code, you can see a basic usage of SQLite Encryption example. You just need to instance a Properties, put a "key" property and set the key as the value. Then, you just need to open a new connection passing the properties as an argument.

Instead of the **key**, you can also pass **hexkey** or **textkey** as the key argument.

```java
Properties props = new Properties();
props.put("key", new Properties.Str("'secret-password'"));
Connection con = DriverManager.getConnection("jdbc:sqlite:" + Convert.appendPath(Settings.appPath, "database.db"), props);
```

{% hint style="warning" %}
**Attention**: the key must be between **single quotes**.
{% endhint %}

### **Changing the encryption key**

There also exists the **rekey** property(and, equivalently, hexrekey and textrekey) which can be used to change the database encryption key. Usage example:

```java
Properties props = new Properties();
props.put("key", new Properties.Str("'secret-password'"));
props.put("rekey", new Properties.Str("'new-password'"));
Connection con = DriverManager.getConnection("jdbc:sqlite:" + Convert.appendPath(Settings.appPath, "database.db"), props);
```

### **Removing the encryption key**

To remove the encryption from the bank and save it on the original format, you just have to use rekey and set a empty value: (but obviously, you need the original key)

```java
Properties props = new Properties();
props.put("key", new Properties.Str("'secret-password'"));
props.put("rekey", new Properties.Str("''"));
Connection con = DriverManager.getConnection("jdbc:sqlite:" + Convert.appendPath(Settings.appPath, "database.db"), props);
```


# QR Code Generator

## Overview

QR codes are a popular type of two-dimensional barcode.They can store up to 4,296 alphanumeric characters of arbitrary text. This text **can be numerical, alphanumerical or binary**, for example URL, contact information, a telephone number.&#x20;

QR codes can be read by an optical device with the appropriate software like a totalcross application or even your phone's camera. To see how to make a qrcode reader click [here](https://totalcross.gitbook.io/playbook/apis/barcode-scanner).

## Usage

To generate the QR Code just instantiate a QRCode Image and call the method **`generate(ecc,str)`** passing as parameters the ECC, which is the quality of the generated code (better in the next topic) and the text of QRCode.&#x20;

See the example below:

{% code title="QRCode\_Sample" %}

```java
import totalcross.qrcode.QRCode;
import totalcross.sys.Settings;
import totalcross.ui.Container;
import totalcross.ui.Control;
import totalcross.ui.ImageControl;
import totalcross.ui.Label;
import totalcross.ui.ScrollContainer;
import totalcross.ui.image.Image;
import totalcross.ui.image.ImageException;
import totalcross.util.UnitsConverter;

public class SampleQRCodeView extends ScrollContainer{
	private String text;
	public void initUI(){
		text = new String ("I am a QRCode :)");					
		QRCode.DEBUG = true;									
		addCard(this, text);									
	}
	
	private Image getImage (String text, int size){
		Image image = new QRCode().generate(QRCode.ECC_QUARTILE, text);
		
		try{
			image = image.getScaledInstance(size, size);		
		}catch(ImageException e){
			e.printStackTrace();
		}
		
		return image;													
	}
	
	private void addCard (Container container, String text){
		int size = (int)(Math.min(Settings.screenWidth, Settings.screenHeight) * 0.8);	
		Image image = getImage(text, size);								
		
		Label label = new Label(text);									
		label.autoSplit = true;
		container.add(label, CENTER, TOP, Control.PARENTSIZE, Control.PREFERRED);		
		container.add(new ImageControl(image), Control.CENTER, Control.AFTER + UnitsConverter.toPixels(Control.DP + 30), size, size);
	}
}

```

{% endcode %}

It is noteworthy that, depending on the type and complexity of the text entered, the version of QRCode generated changes. The choice of the appropriate version for the past text happens internally. To see which version was chosen, simply pass true in the QRCode Debug attribute(`QRCode.DEBUG = true;`),as in line 16 of the code above.

### Error Correction Level

The ECC, as commented above, ECC corresponds to Error Correction Level and they are:

| Error Correction Level | Description                            |
| ---------------------- | -------------------------------------- |
| `ECC_LOW`              | Allows recovery of up to 7% data loss  |
| `ECC_MEDIUM`           | Allows recovery of up to 15% data loss |
| `ECC_QUARTILE`         | Allows recovery of up to 25% data loss |
| `ECC_HIGH`             | Allows recovery of up to 30% data loss |

{% hint style="info" %}
By default, totalcross uses `ECC_QUARTILE`
{% endhint %}

## References

* See more in <https://www.qrcode.com/en>
* Download the full QRCode generator example [here](https://github.com/TotalCross/QRCode_Sample/)


# totalcross.sys

## Settings

This class provides some preferences from the device configuration and other VM settings. All settings are read-only, unless otherwise specified. Changing their values may cause the VM to crash. Look at its JavaDoc for more details.

## **VM**

Vm contains various system-level methods. This class contains methods to copy arrays, obtain a timestamp, sleep, and get platform and version information, among many other things. Look at its JavaDoc for more details.

## Time

The Time class stores a specific a date and time.&#x20;

* The **year** must have **4 digits**&#x20;
* The **hour** is **numbered in 24-hour notation**, which is the international standard notation of time, and may also be referred as military time or astronomical time.

For performance reasons, the Time fields have public access. So you can directly access the field day to get or set its value, instead of calling a method. However, that makes the Time objects unsafe because the fields’ values are not checked when they are set, and may not be within the field valid range.

Since the fields can be set without any kind of validation, it would be pointless to add validation to the other methods, therefore, the Time fields’ values are never validated by any method or constructor. So you must know and always respect the fields’ range, and never set a field with a variable without first checking if the value is withing range (for instance, let the user type the hour in an edit and simply convert it to int and set the hour field, without checking if its value is between 0 and 23).

The Time fields with their respective range:

* **year:** The year in 4 digits;
* **month:** The month in the range of 1 to 12;
* **day:** The day in the range of 1 to the last day of the specified month;
* **hour:** The hour in the range of 0 to 23;
* **minute:** The minute in the range of 0 to 59;
* **second:** The second in the range of 0 to 59;
* **millis:** Milliseconds in the range of 0 to 999;

{% hint style="info" %}
Time has a constant called **SECONDS\_PER\_DAY**, which obviously represents the **number of seconds** in a day, being equal to 24 \* 3600.
{% endhint %}

### Constructors&#x20;

Time has six constructors:

* **Time()**: Default constructor, creates a Time object set with the device’s current date and time. Most devices do not keep track of the milliseconds, therefore, the field millis of the new object will always have the default value 0 on them.
* **Time(int year, int month, int day, int hour, int minute, int second, int millis):** Creates a Time object with the given values.
* **Time(long t):** Creates a Time object from the given value, which must be in the format YYYYMMDDHHMMSS.
* **Time(int yyyymmdd, int hhmmssmmm):** Constructs a Time object from the given date and time values.
* **Time(String iso8601):** Creates a Time object using the given string, which must be in the ISO8601 format: YYYYMMDDTHH:MM:SS.

{% hint style="warning" %}
Please notice the last three constructors do not include the milliseconds, so the field millis will keep its default value 0.
{% endhint %}

* **Time(String time, boolean hasYear, boolean hasMonth, boolean hasDay, boolean hasHour, boolean hasMinute, boolean hasSeconds):** Constructs a Time object, parsing the string and placing the fields depending on the flags that were set, using Settings.timeSeparator as spliter. The number of parts must match the number of true flags, or an `ArrayIndexOutOfBoundsException` will be thrown. AM/PM is supported.

{% hint style="warning" %}
**Remember**: no kind of validation is done on the Time fields values, not even on the constructors. However, the default constructor will never initialize an object with invalid values, and the last two constructors may throw an InvalidNumberException if it fails to parse the given string.
{% endhint %}

### Methods&#x20;

Finally, Time has the following methods:

* **`update()`**: Updates the internal fields with the current timestamp.
* **`quals(Object o)`:** Compares two Time objects for equality. The result is true if and only if the argument is not null and it’s a Time object that represents the same point in time, from year to millisecond, as this object.
* **`getTimeLong()`:** Converts this Time object to a long value in the format\
  YYYYMMDDHHMMSS. Milliseconds is not included.YYYYMMDDHHMMSS. Milliseconds is not included.
* **`toIso8601()`**: Converts this Time object to a string in the ISO8601 format:\
  YYYYMMDDTHH:MM:SS. Milliseconds is not included.
* **`toString()`**: Returns the time in format specified in totalcross.sys.Settings (does NOT include the date neither the milliseconds). To return the date, use the class totalcross.util.Date. So, to get a string with the date and time, use:
  * `Time t = new Time();`&#x20;
  * `String dateAndTime = new Date(t) + " " + t;`
* **`toString(String timeSeparator)`**: Similar to the above method except that it uses the specified separator.
* **`dump(StringBuffer sb, String timeSeparator, boolean includeMillis)`** : Dumps the time into the given StringBuffer, using the given separator and including the millileconds if asked by the user.
* **`isValid()`**: Returns true if the time is valid. Note that the date part is NOT checked; only hour, minute, second, and millis are checked against valid ranges.
* **`inc(int hours, int minutes, int seconds)`**: Increments or decrements the fields below. Note that this method does NOT update the day/month/year fields. The parameters can be positive (to increment), zero (to keep it), or negative (to decrement).

## CharacterConvert

This class is used to correctly handle international character conversions. The default character scheme converter is the 8859-1 (ISO Latin 1).&#x20;

If you want to use a different one, you must extend this class, implementing the `bytes2chars()` and `chars2bytes()` methods, and then assign the public member of `Convert.charConverter` to use your class instead of this default one. You can also use the method `Convert.setDefaultConverter()` to change it, passing, as parameter, the prefix of your CharacterConverter class (better look at the implementation to know what to pass on).&#x20;

For example, if you created a class named Iso88592CharacterConverter, call

```java
Convert.setDefaultConverter("Iso88592");
```

To find out which `sun.io.CharacterEncoder` you’re using on JDK to implement an equivalent version for TotalCross, use:

```java
System.out.println("" + sun.io.ByteToCharConverter.getDefault());
```

## UTF8CharacterConvert

This class extends the CharacterConvert class, and implements the UTF8 byte to UCS-2 character conversion. To use this class, you can call:

```java
Convert.setDefaultConverter("UTF8");
```

## Convert

Convert basically provides methods that allows object and basic type conversion. Furthermore, it also provides handy methods for common operations that should be used for a better performance.

This class is final and cannot be instantiated – its methods and fields are static.

To give you a better view of this class, its documentation was split into sub-sections:

### **Changing the default character converter**

The field charConverter keeps a reference to a character converter that will be used by default. You may change it by setting another character converter of your choice.

You may also use the method `setDefaultConverter(String name)`, which searches for a character converter by its name, and makes it the default by changing the charConverter field. Use like

```java
Convert.setDefaultConverter("UTF8");
```

to change all bytes\_to\_char and `char_to_bytes` operations to use UTF8 instead. Issuing

```java
Convert.setDefaultConverter("");
```

sets back the default encoder. The method returns true if the given encoder was found; false, otherwise. If not found, the encoder is reseted to the default one (ISO 8859-1).

### **Conversion between String and basic types**

| **Method**                             | Definition                                                                                                                                                                                 |
| -------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
| toDouble(String s)                     | Converts the given string to double.                                                                                                                                                       |
| toInt(String s)                        | Converts the given string to int. The number may be prefixed with 0’s.                                                                                                                     |
| toShort(String s)                      | Convert a string to the short type. Note that this method is slower than (short)Convert.toInt(). However, it will throw an InvalidNumberException if the number is out of the short range. |
| toLong(String s)                       | Converts the given string to long.                                                                                                                                                         |
| <p>toLong(String s, int radix)<br></p> | Converts the given string to long in the given radix, which must be between 2 and 16.                                                                                                      |
| <p>toString(boolean b) <br></p>        | Converts the given boolean to a string.                                                                                                                                                    |
| toString(char c)                       | Converts the given char to a string.                                                                                                                                                       |
| toString(double d)                     | Converts the given double to a string, formatted in scientific notation.                                                                                                                   |
| toString(double val, int decimalCount) | Converts the given double to a string, formatted with the given number of decimal places.                                                                                                  |
| toString(int i) Converts               | the given int to a string.                                                                                                                                                                 |
| toString(long l)                       | Converts the given long to a string using base 10.                                                                                                                                         |
| toString(long i, int radix)            | Converts the given long to a string in the given radix, which must be between 2 and 16.                                                                                                    |
| toString(String doubleValue, int n)    | Formats the given string as a double, rounding with n decimal places.                                                                                                                      |
| unsigned2hex(int b, int places)        | Converts the given unsigned integer to hexadecimal using the given number of places (up to 8).                                                                                             |

### **Character, String and StringBuffer utilities**

| **Method**                                                                          | Definition                                                                                                                                               |
| ----------------------------------------------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------- |
| <p></p><p>appendPath(String path1, String path2)</p>                                | Concatenates two strings, ensuring there’s a single slash between them. Removes extra slashes or backslashes if necessary.                               |
| digitOf(char ch, int radix)                                                         | Returns the value of the digit stored as char in the specified radix, which must be between 2 and 16. This method only handles the standard ASCII table. |
| dup(char c, int count)                                                              | Returns a string filled with the given char and size equals to count.                                                                                    |
| forDigit(int digit, int radix)                                                      | Returns the given digit in the specified radix, which must be between 2 and 16.                                                                          |
| getBreakPos(FontMetrics fm,StringBuffer sb,int start, int width,boolean doWordWrap) | Finds the best position to break the line with the given width, respecting word-wrap option and line endings                                             |
| hashCode(StringBuffer sb)                                                           | Returns the hash code of the string stored by this StringBuffer.                                                                                         |

{% hint style="warning" %}
The class StringBuffer does not have a method that returns its hash code, so you would have to first create a String from the StringBuffer to get its hash code, like this: \
\
`int hashCode = sb.toString.hashCode();`&#x20;
{% endhint %}

| **Method**                                                 | Definition                                                                                                                                                                                                                                                                                      |
| ---------------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| Convert.hashCode()                                         | calculates the StringBuffer’s hash code directly, without using an intermediary String object, resulting in better performance and memory usage.                                                                                                                                                |
| insertAt(StringBuffer sb, int pos, char c)                 | Inserts the given char at the specified position in the StringBuffer.                                                                                                                                                                                                                           |
| insertLineBreak(int maxWidth, FontMetrics fm, String text) | Returns a new string which is a copy of the given text with line breaks, placed based on the maxWidth and fm arguments. Very useful method to help you keep your application’s interface cross-platform. It can be used to insert line breaks on strings passed to message boxes or list boxes. |
| insertLineBreak(int maxWidth, FontMetrics fm, String text) | Returns a new string which is a copy of the given text with line breaks, placed based on the maxWidth and fm arguments. Very useful method to help you keep your application’s interface cross-platform. It can be used to insert line breaks on strings passed to message boxes or list boxes. |
| numberOf(String s, char c)                                 | Returns the number of occurrences of the specified char in the given string.                                                                                                                                                                                                                    |
| replace(String source, String from, String to)             | Searches the string source for occurrences of the string from, replacing them by the string to.                                                                                                                                                                                                 |
| tokenizeString(String input, char delim)                   | Tokenizes the given string using the given char as separator. The return is a string array with size equal to the number of tokens.                                                                                                                                                             |
| <p>tokenizeString(String input, String delim) <br></p>     | Same as the above, but uses a String instead of a char as separator. Never use this method with 1 character length strings, like: `String[] tokens = Convert.tokenizeString(input, “#”);`                                                                                                       |

Use the previous method instead for better performanc&#x65;**:**

* **`toLowerCase(char c)`**: Converts the given char to lower case.<br>
* **`toUpperCase(char c)`**: Converts the given char to upper case.<br>
* **`zeroPad(String s, int size)`**: Pads the string, adding zeros at left.<br>
* **`zeroUnpad(String s)`**: Removes left zeros of the string.

### **Arrays**

|                                  |                                                                                                |
| -------------------------------- | ---------------------------------------------------------------------------------------------- |
| cloneStringArray(String\[] strs) | Returns a copy of the given string array.                                                      |
| toStringArray(Object\[] objs)    | Converts the given object array into a string array, by calling toString() for each object.    |
| detectSortType(Object item)      | Returns the sort type for the given item sample (which is usually the first item of an array). |

Convert provides the quick sort algorithm for array sorting.

### Constants

* **SORT\_AUTODETECT** - Chooses between one of the sort types below based on the first element of the array.
* **SORT\_OBJECT** - The objects are compared by their string representation.
* **SORT\_STRING** - The array contains String objects, and the sort is case sensitive.
* **SORT\_INT** - The array contains String objects that represents integer values.
* **SORT\_DOUBLE** - The array contains String objects that represents double values.
* **SORT\_DATE** - The array contains String objects that represents a Date object with day, month, and year.
* **SORT\_COMPARABLE** - The array contains comparable objects (objects that implements the Comparable interface).
* **SORT\_STRING\_NOCASE** - The array contains String objects, and the sort is case insensitive, which is slower than case sensitive sorting.

### **Methods**

* **qsort(Object\[] items, int first, int last) -** Applies the quick sort algorithm to the elements of the given array, sorting in ascending order and sort type equals to SORT\_AUTODETECT.<br>
* **qsort(Object\[] items, int first, int last, int sortType)** - Same as the above method, but you can specify the sort type.<br>
* **qsort(Object\[] items, int first, int last, int sortType, boolean ascending)** - Same as the above, but you can also choose between sorting in ascending or descending order.

### **Other Conversions and Methods**

* **chars2int(String fourChars)** - Converts a creator id or type to int.
* **int2chars(int i)** - Converts an int to a creator id or type.
* **doubleToIntBits(double f)** - Converts the given double to its bit representation in IEEE 754 format, using 4 bytes instead of 8 (a conversion to float is applied).
* **intBitsToDouble(int i)** - Converts the given IEEE 754 bit representation of a float to a double.
* **doubleToLongBits(double value)** - Returns a representation of the specified floating-point value according to the IEEE 754 floating-point "double format" bit layout.
* **longBitsToDouble(long bits)** - Converts the given bit representation to a double.
* **rol(long i, int n, int bits)** - Does a rol of n bits in the given long. n must be < bits. Unlike the shift left operator (<<), bits that would have been lost are reinserted in order at the right.
* **ror(long i, int n, int bits)** - Does a ror of n bits in the given long. n must be < bits. Unlike the shift right operator (>>), bits that would have been lost are reinserted in order at the left.

### **Another Useful Constants**

| **Constants**                     |                                                                                 |
| --------------------------------- | ------------------------------------------------------------------------------- |
| CRLF                              | \r\n.                                                                           |
| CRLF\_BYTES                       | {’\r’,’\n’}                                                                     |
| MAX\_SHORT\_VALUE                 | The maximum short value: 32767                                                  |
| MIN\_SHORT\_VALUE                 | The minimum short value: -32768.                                                |
| MIN\_INT\_VALUE                   | The minimum int value: -2147483648                                              |
| MAX\_INT\_VALUE                   | The maximum int value: 2147483647.                                              |
| MIN\_LONG\_VALUE                  | The minimum long value: -9223372036854775808.                                   |
| MAX\_LONG\_VALUE                  | The maximum long value: 9223372036854775807                                     |
| MAX\_DOUBLE\_VALUE                | The maximum double value: 9.007199254740992E15.                                 |
| MIN\_DOUBLE\_VALUE                | The minimum double value: 1.1102230246251565E-16.                               |
| MAX\_DOUBLE\_DIGITS               | The maximum number of digits in a double value, used when formatting to string. |
| DOUBLE\_POSITIVE\_INFINITY\_VALUE | The double that represents a positive infinity.                                 |
| DOUBLE\_NEGATIVE\_INFINITY\_VALUE | The double that represents a negative infinity.                                 |
| DOUBLE\_POSITIVE\_INFINITY\_BITS  | The long whose bits represent a positive infinity.                              |
| DOUBLE\_NEGATIVE\_INFINITY\_BITS  | The long whose bits represent a negative infinity.                              |
| DOUBLE\_NAN\_BITS                 | The long whose bits represent a Not a Number (NaN).                             |


# Youtube API

### Overview

Api from youtube allows you to watch a video from youtube on the devices (Android and IOS) using TotalCross.

### Source Code

{% code title="Youtube Example" %}

```java
public class YoutubeDemo extends MainWindow {
    @Override
    public void initUI() {
        Edit.useNativeNumericPad = true;
        Edit startEdit = new Edit();
        startEdit.caption = "start (s)";
        startEdit.setKeyboard(Edit.KBD_NUMERIC);
        startEdit.setText("0");
        Edit endEdit = new Edit();
        endEdit.caption = "end (s)";
        endEdit.setKeyboard(Edit.KBD_NUMERIC);
        startEdit.setText("0");
        Check auto = new Check("autoPlay");
        add(startEdit, CENTER, AFTER + UnitsConverter.toPixels(DP + 16),
                PARENTSIZE + 80, PREFERRED);
        add(endEdit, CENTER, AFTER + UnitsConverter.toPixels(DP + 16),
                PARENTSIZE + 80, PREFERRED);
        add(auto, CENTER, AFTER + UnitsConverter.toPixels(DP + 16),
                PARENTSIZE + 80, PREFERRED);

        Button b = new Button("Open Video");
        add(b, CENTER, AFTER + UnitsConverter.toPixels(DP + 16));

        b.addPressListener((c) -> {
            try {
                int start = startEdit.getText() == null? 0 : (int) Double.parseDouble(startEdit.getText());
                int end = endEdit.getText() == null? -1 : (int) Double.parseDouble(endEdit.getText());
                boolean autoPlay = auto.isChecked();
                new YoutubePlayer()
                        .start(start)
                        .end(end)
                        .autoPlay(autoPlay)
                        .play("o07Ju5snaCw",
                                (state) -> System.out.println("State: " + state));
            } catch (Exception e) {
                new MessageBox("Erro", e.getMessage()).popup();
            }
        });
    }
```

{% endcode %}

### Attributes

| Type                 | Name                     | Description                                      |
| -------------------- | ------------------------ | ------------------------------------------------ |
| **static final int** | STATE\_UNSTARTED         | is a state of when the video has not started yet |
| **static final int** | STATE\_ENDED             | is a state of when the video ended               |
| **static final int** | STATE\_PLAYING           | is a state of when the video is still playing    |
| **static final int** | STATE\_PAUSED            | is a state of when the video is still paused     |
| **static final int** | STATE\_BUFFERING         | is a state of when the video is still loading    |
| **static final int** | STATE\_CUED              | is a state of when the video is still cued       |
| **static final int** | STATE\_UNKNOWN           | when the player does not know what current state |
| **static final int** | ERROR\_VIDEO\_NOT\_FOUND | when the video was not found                     |
| **static final int** | ERROR\_UNKNOWN           | Unknown error happened                           |

### Methods

| Type              | Name                               | Description                                                                                      |
| ----------------- | ---------------------------------- | ------------------------------------------------------------------------------------------------ |
| **YoutubePlayer** | autoPlay                           | Sets the video to play automatically when it's loaded.                                           |
| **YoutubePlayer** | end                                | Sets the end point in seconds of the video.                                                      |
| **YoutubePlayer** | start                              | Sets the start point in seconds of the video.                                                    |
| **void**          | play(String id)                    | plays the video that was passed in id                                                            |
| **void**          | play(String id, Callback callback) | plays the video that was passed in the id and has a callback to inform which state of the player |

## References

* You can view the code shown above in [github](https://github.com/TotalCross/YoutubeSample)


# Creating an Issue

This article aims to show the best practices when opening an issue.

Reporting an issue is one of the most important activities for the software evolution life cycle. This process helps the maintainers to define the most relevant features their product must have and find critical bugs. However, an issue badly reported can leads the maintainers to waste a great amount of time investigating the real cause of the problem reported. For instance, a not well structured will generate doubts causing the developers to waste their time with questions and waiting for the answers (and if you know what I mean, programmers don't like interacting that much 😅).

Thus, this guide will teach you the correct way of creating good issues by showing some examples and explaining the most required information an issue must have in order to be solved in short time.

{% hint style="warning" %}
We emphasize the importance of answering questions from the support team **as quickly as possible** so that neither party is left with idle time.
{% endhint %}

## Issue Structure

To avoid these situations and optimize the resolution time of the problem, we advise that the issues contain the following structure

* Title;&#x20;
* Description (the error and the situation in which it occurs).
  * Visual representation (Screenshots / GIF / Video);&#x20;
  * Code to reproduce the error;&#x20;
  * Error log.

## Title

When creating the Title, **it is necessary to define the problem in a sentence** so at the first look it is already possible to have an idea of the **severity** (and in some cases of the **type**) of the Issue.

Example:

> **Error opening camera to record video on Moto G Android 6.0**

## Description

After the title, it is now necessary to detail **what the error is and in what situations it occurs**. This makes it easier to identify the cause of the problem and makes it much easier to **reproduce the error and test the solution**.

In the description it is also of utmost importance that it be said which **version of TotalCross is being used, on which devices you are having problems and which version of the operating system.**

Example:

> I'm trying to call the camera in video mode on the Moto G Turbo Edition with Android 6.0, but without success. In this case, I'm with two problems
>
> • When calling the camera in Native mode, even if the Video with Audio option is set, the system opens the camera in Photo mode • When calling the camera in Custom mode when I click the Start button. the program crashes
>
> My question is whether there is any way to force the native camera to go into video mode or if you are forced to use the camera Custom, what can be done about the error that is occurring.
>
> I made an example code that exactly reproduces the above problems:

That done, half of the description is ready but there are still some points of paramount importance. Are they:

### Visual Representation

To give more context to the problem and to accurately illustrate what is happening, it is interesting that screenshots, GIFs or videos be attached to the issue so that we can have a better view of what is happening.

Example:

![](/files/-M-KejMaQ95ehFEp8kMI)

### Code to reproduce the error

In order to reproduce the error, the code must also be sent. It can be the original of your application or an example (as long as it faithfully reproduces the error you are getting in the original application).

Example:

```java
Button btnCameraVideoOnly;
Button btnCamera;
Button btnNativeCameraVideoOnly;
Button btnNativeCamera;

@Override
public void initUI() {
    Button btnExit = new Button("Exit");
    btnExit.paddingLeft = btnExit.paddingRight = 20;
    btnExit.paddingTop = btnExit.paddingBottom = 10;
    btnExit.addPressListener(e -> MainWindow.exit(0));
    add(btnExit, CENTER, CENTER);

    btnCameraVideoOnly = new Button("Open Camera w/o Audio");
    btnCameraVideoOnly.paddingLeft = btnExit.paddingRight = 20;
    btnCameraVideoOnly.paddingTop = btnExit.paddingBottom = 10;
    add(btnCameraVideoOnly, CENTER, BEFORE-4);

    btnCamera = new Button("Open Camera w/ Audio");
    btnCamera.paddingLeft = btnExit.paddingRight = 20;
    btnCamera.paddingTop = btnExit.paddingBottom = 10;
    add(btnCamera, CENTER, BEFORE-4);

    btnNativeCameraVideoOnly = new Button("Open Native Camera w/o Audio");
    btnNativeCameraVideoOnly.paddingLeft = btnExit.paddingRight = 20;
    btnNativeCameraVideoOnly.paddingTop = btnExit.paddingBottom = 10;
    add(btnNativeCameraVideoOnly, CENTER, BEFORE-4);

    btnNativeCamera = new Button("Open Native Camera w/ Audio");
    btnNativeCamera.paddingLeft = btnExit.paddingRight = 20;
    btnNativeCamera.paddingTop = btnExit.paddingBottom = 10;
    add(btnNativeCamera, CENTER, BEFORE-4);
}

@Override
public <H extends EventHandler> void onEvent(Event<H> event) {
    try {
        if (event.type == ControlEvent.PRESSED) {
            if (event.target == btnCameraVideoOnly) {
                Camera camera           = new Camera();
                camera.cameraType       = totalcross.ui.media.Camera.CAMERA_CUSTOM;
                camera.captureMode      = totalcross.ui.media.Camera.CAMERACAPTURE_MODE_VIDEOONLY;
                camera.click();
            }
            else if (event.target ==  btnCamera) {
                Camera camera           = new Camera();
                camera.cameraType       = totalcross.ui.media.Camera.CAMERA_CUSTOM;
                camera.captureMode      = totalcross.ui.media.Camera.CAMERACAPTURE_MODE_VIDEOWITHAUDIO;
                camera.click();
            }
            else if (event.target == btnNativeCameraVideoOnly) {
                Camera camera           = new Camera();
                camera.cameraType       = totalcross.ui.media.Camera.CAMERA_NATIVE;
                camera.captureMode      = totalcross.ui.media.Camera.CAMERACAPTURE_MODE_VIDEOONLY;
                camera.click();
            }
            else if (event.target == btnNativeCamera) {
                Camera camera           = new Camera();
                camera.cameraType       = totalcross.ui.media.Camera.CAMERA_NATIVE;
                camera.captureMode      = totalcross.ui.media.Camera.CAMERACAPTURE_MODE_VIDEOWITHAUDIO;
                camera.click();
            }
        }
    } catch (Exception e) {
        e.printStackTrace();
    }
}
```

{% hint style="info" %}
If the code sent is **private** then just put the issue as **confidential** (so only our team and the issue creator will have access) or send it to us via [Slack ](https://totalcrossclients.slack.com/messages)(Exclusive service channel for mobile clients).
{% endhint %}

### Error Log

In addition to the code, it is also necessary to send the Error Log for the code in question, as some errors may occur due to machine configurations (both computer and mobile phones) so on one machine it can occur and on others it cannot. The Log also details the error better.

Exemple:

```java
12-16 10:15:45.305 15740 15740 I TotalCross: NON-FATAL EXCEPTION
12-16 10:15:45.305 15740 15740 I TotalCross: java.lang.RuntimeException: setAudioSource failed.
12-16 10:15:45.305 15740 15740 I TotalCross:    at android.media.MediaRecorder.setAudioSource(Native Method)
12-16 10:15:45.305 15740 15740 I TotalCross:    at totalcross.appdtem.CameraViewer.startRecording(CameraViewer.java:206)
12-16 10:15:45.305 15740 15740 I TotalCross:    at totalcross.appdtem.CameraViewer.access$300(CameraViewer.java:37)
12-16 10:15:45.305 15740 15740 I TotalCross:    at totalcross.appdtem.CameraViewer$2.onClick(CameraViewer.java:299)
12-16 10:15:45.305 15740 15740 I TotalCross:    at android.view.View.performClick(View.java:6600)
12-16 10:15:45.305 15740 15740 I TotalCross:    at android.view.View.performClickInternal(View.java:6577)
12-16 10:15:45.305 15740 15740 I TotalCross:    at android.view.View.access$3100(View.java:781)
12-16 10:15:45.305 15740 15740 I TotalCross:    at android.view.View$PerformClick.run(View.java:25912)
12-16 10:15:45.305 15740 15740 I TotalCross:    at android.os.Handler.handleCallback(Handler.java:873)
12-16 10:15:45.305 15740 15740 I TotalCross:    at android.os.Handler.dispatchMessage(Handler.java:99)
12-16 10:15:45.305 15740 15740 I TotalCross:    at android.os.Looper.loop(Looper.java:193)
12-16 10:15:45.305 15740 15740 I TotalCross:    at android.app.ActivityThread.main(ActivityThread.java:6923)
12-16 10:15:45.305 15740 15740 I TotalCross:    at java.lang.reflect.Method.invoke(Native Method)
12-16 10:15:45.305 15740 15740 I TotalCross:    at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:493)
12-16 10:15:45.305 15740 15740 I TotalCross:    at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:870)
```

{% hint style="success" %}
There are cases in which just by looking at the log the support team can already identify what the problem is and how to solve it.
{% endhint %}

## References

All examples were taken from real and public issues that are in our repository. Are they:

* [Issue #639](https://gitlab.com/totalcross/TotalCross/issues/639)
* [Issue #550](https://gitlab.com/totalcross/TotalCross/issues/550)

If you don't know how to access your application's log while it runs on mobile phones then we recommend the following tutorials:

* [Realtime Debugging for Unity Android Apps - ADB LogCat Tutorial](https://www.youtube.com/watch?v=eI2GOuEMGfQ)
* [ADB ](https://www.youtube.com/watch?v=3wMlCucwGvE)[Tutorial -](https://www.youtube.com/watch?v=3wMlCucwGvE) [How to use ADB](https://www.youtube.com/watch?v=3wMlCucwGvE)


# Contributing

Learn how to contribute to TotalCross.


# Branch workflow

Understand our git workflow

## Types

There are some types of branches in our repository, they are:

* **Feature**: used to implement new features. Can be started from an issue. Started at the source of the problem (commit) from the source version. The prefix is `feature-`;
* **Fix**: used to fix bugs and code smells. Can be started from an issue. Started at the source of the problem (commit) from the source version. Fix takes precedence over the feature and should be resolved quickly and has the same process. The prefix is: `fix-`;
* **Hotfix**: special branches for cases of emergency corrections, are used to quickly patch production releases. The prefix is `hotfix-`;
* **Develop**: **WIP**
* **Master**: **WIP**

## **Rebase before merge**

In summary:

1. Open branch `feature-x`;
2. `develop`does not stop production ;
3. Finish `feature-x`;
4. Rebase `feature-x` into `develop`;
5. Test integration;
6. Merge request (delete the branch).

The reasons for this are:&#x20;

* Anticipate integration;
* Maintain a more linear history;
* Commit squash situation (compile multiples commits in an unique commit).


# Writing documentation

Component documentation template

Our component documentation standard model is based on our [Check](https://learn.totalcross.com/components/checkbox) component doc. Please, check it out.

Feel free to download our Component Doc Template guidelines below.

{% file src="/files/-M3v1mXEMQpZNNYgDLKU" %}
Download out Component Doc Template
{% endfile %}


# Guides


# App Architecture


# Suggested Architecture

## Overview

This guide is intended for developers who have already completed getting started and have a basic understanding of TotalCross UI components, SQLite, Deploy, and Web Services, and now want to know about the architecture and best practices for building more robust and better quality apps.

If you are not already familiar with the TotalCross framework we strongly recommend you to read the entire previous session (Learning TotalCross), beginning with Getting Started.

{% content-ref url="/pages/-L\_nYhQejLO1mcNnETZN" %}
[Broken mention](broken://pages/-L_nYhQejLO1mcNnETZN)
{% endcontent-ref %}

## The mobile user experience

In most cases, computer applications have a single point of entry into a desktop or quick access to programs, and then run as a single monolithic process.&#x20;

Mobile apps, on the other hand, have a more complex structure. A standard mobile app contains several components, including Containers, Windows, services, content providers, and calls to native components such as camera or calls.

And when we are developing multiplatform we still have to think more deeply, remembering the particularities of each Operating System to which we want to make the application available. Although TotalCross already does the trickiest part of generating executables and preserving performance, you also need to think about the structure, modeling and configuration of the App.

## Recommended App Architecture

We've separated some suggestions for the architecture of your app.&#x20;

### Why do Design Patterns help with the application's organization?

{% content-ref url="/pages/-L\_mnBHWXYrJToJbOudr" %}
[Why do Design Patterns help with the application's organization?](/master/documentation/guides/app-architecture/suggested-design-patterns)
{% endcontent-ref %}

### Separation of concepts: What is the best way to create UI interfaces?

{% content-ref url="/pages/-L\_ml9iy2SivE5II\_fAX" %}
[Separation of concepts: What is the best way to create UI interfaces?](/master/documentation/guides/app-architecture/container-x-window)
{% endcontent-ref %}

### Positioning

{% content-ref url="/pages/-L\_mlBZVsEQnFcwLCNDl" %}
[Positioning](/master/documentation/guides/app-architecture/relative-positioning)
{% endcontent-ref %}

### Best Practices to improve project maintenance

{% content-ref url="/pages/-L\_mmqbkt3Ej78Xq3t1R" %}
[Best practices to improve project maintenance](/master/documentation/guides/app-architecture/colors-fonts-and-images)
{% endcontent-ref %}


# Why do Design Patterns help with the application's organization?

The design patterns will help in the structure of your application, because they will serve in the construction of the application, leaving the code leaner, clean and organized, that is, it will be more practical to correct errors and implement new functionalities resulting in a greater longevity application. See the examples of some patterns we recommend

### Architecture Pattern

{% content-ref url="/pages/-L\_mnKMKjQVVMqRqIBZE" %}
[MVC Architecture Pattern](/master/documentation/guides/app-architecture/suggested-design-patterns/mvc)
{% endcontent-ref %}

### Style management pattern

{% content-ref url="/pages/-L\_mnHQn3bY3olIbGVu4" %}
[Template Pattern](/master/documentation/guides/app-architecture/suggested-design-patterns/builder)
{% endcontent-ref %}

### Structural pattern

{% content-ref url="/pages/-L\_mnPd7phTXslbzFmSP" %}
[Data Persistence: DAO Pattern.](/master/documentation/guides/app-architecture/suggested-design-patterns/dao)
{% endcontent-ref %}


# MVC Architecture Pattern

This architecture pattern will assign and separate the objects into responsibilities: **Model**, **View** and **Controller**

* **Model:** will represent an object, such as a person.
* **View:** The view will represent the model data.
* **Controller:** It controls the data of the model object and controls the visualization.

### Structures

{% code title="Structures" %}

```
└── src
    └── main
        └── java
            └── com.your_company_name.your_name_app
                └── model
                    └── Person
                └── view
                    └── HomeView
                └── controller
                    └── HomePresenter
```

{% endcode %}

{% tabs %}
{% tab title="Person - Model" %}

```java
package com.totalcross.mvc.model;

public class Person {
    private String name;
    private String gender;

    public Person(String name, String gender) {
        this.name = name;
        this.gender = gender;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public String getGender() {
        return gender;
    }

    public void setGender(String gender) {
        this.gender = gender;
    }

    @Override
    public String toString() {
        return "n: " + name + " g: " + gender;
    }
}

```

{% endtab %}

{% tab title="HomeScreeen - View" %}

```java
package com.totalcross.mvc.view;

import com.totalcross.mvc.controller.HomePresenter;
import com.totalcross.mvc.model.Person;
import totalcross.ui.Button;
import totalcross.ui.Edit;
import totalcross.ui.Label;
import totalcross.ui.MainWindow;

public class HomeScreen extends MainWindow {

   //Create a variable to store the interface of the class.
    Presenter presenter;

    Person person [] = new Person[5];
    private int gap = 15;

/*
The constructor will be responsible for instantiating the HomePresenter class 
which will link the presenter of the interface with the controller
*/
    public HomeScreen(){
        new HomePresenter(this);
    }

    @Override
    public void initUI() {

        Label lbl = new Label("Person");
        add(lbl, CENTER, TOP + gap);

        Edit editName = new Edit();
        editName.caption = "Insert your name here";
        add(editName, LEFT, AFTER + gap);

        Edit editGender = new Edit();
        editGender.caption = "Insert your gender here";
        add(editGender, LEFT, AFTER + gap);

        Button btn = new Button("Create Person");
        //Assigning the onCreate method to the btn button
        btn.addPressListener( e -> presenter.onCreate(person, editName, editGender));
        add(btn, RIGHT, AFTER + gap);
    }

    //Creating the interface and the methods that will be used on this screen
    public interface Presenter{
        void onCreate(Person[] person, Edit name, Edit gender);
    }

    //Method that allows you to add the Controller Presenter in the view
    public void addListener(Presenter presenter) {
        this.presenter = presenter;
    }


}


```

{% endtab %}

{% tab title="HomePresenter  - Controller" %}

```java
package com.totalcross.mvc.controller;

import com.totalcross.mvc.model.Person;
import com.totalcross.mvc.view.HomeScreen;
import totalcross.ui.Edit;
import totalcross.ui.Toast;

public class HomePresenter implements HomeScreen.Presenter {
/*
    In the constructor the Presenter link of the controller is realized 
    with the view.
*/
    public HomePresenter(HomeScreen home){
        home.addListener(this);
    }
    
    //The method that will be used on the button is implemented.
    @Override
    public void onCreate(Person[] person, Edit name, Edit gender) {
        for (int i = 0; i < person.length; i++) {
            if (person[i] == null){
                person[i] = new Person(name.getText(), gender.getText());
                break;
            }
        }

        String persons = "";
        for (Person p: person) {
            persons += p + " / ";
        }
        Toast.show(persons,2000);
        System.out.println(persons);
    }
}

```

{% endtab %}
{% endtabs %}

## Referencies

* See more about MVC in [Geeks for Geeks](https://www.geeksforgeeks.org/mvc-design-pattern/).&#x20;


# Template Pattern

### What's Template Pattern

In this pattern, we will use an enum that will be responsible for providing a stylization for your controls, thus making your code less coupled and more practical to be developed

For example, in your application has a color pattern, font size and a particular font, you can create an enum that will represent this stylization for you and in case you need to change something in those controls you just need to change that enum.&#x20;

### How to apply this method

For example if in your application you have a need to create custom labels with a specific font and with different font sizes

#### Create a enum

You can create the enum in the root of the controller package

{% code title="Structures " %}

```
└── src
    └── main
        └── java
            └── com.your_company_name.your_name_app
                .
                .
                .
                └── controller
                    └── Template.java
```

{% endcode %}

{% code title="Template.java" %}

```java
public enum Template {
        
/*

H1 to H4 will be used to stylize the controls with a font, bold style,
font size and forecolor and will be changed between those enum only your fontsize.
 
The parameters of the getFont () method are String font_name,
boolean boldStyle, int size in example h1 we have then:
        "Graviola Soft-Bold": font 
        false: boldStyle
        24: Font size
        0x363D86: forecolor
*/
    H1(Font.getFont("Graviola Soft-Bold", false, 24), 0x363D86),
    H2(Font.getFont("Graviola Soft-Bold", false, 20), 0x363D86),
    H3(Font.getFont("Graviola Soft-Bold", false, 18), 0x363D86),
    H4(Font.getFont("OpenSans-Bold", false, 12), 0x363D86),

    private final Font font;
    private final Integer forecolor;
    
    Template(Font font, Integer forecolor) {
        this.font = font;
        this.forecolor = forecolor;
    }

    public <T extends Control> T apply(T c) {
        if (forecolor != null) {
            c.setForeColor(forecolor);
        }
        
        if (font != null) {
            if (c instanceof Icon) {
                c.setFont(Font.getFont(c.getFont().name, false, font.size));
            } else {
                c.setFont(font);
            }
        }
        
        return c;
    }


```

{% endcode %}

#### To use the template

In your controls now you can use your previously created template to maintain a standard styling.

```java
Label lblHeader= new Label("Header");
Template.H1.apply(lblHeader);
add(lblHeader, CENTER, TOP);
```

The enum template created above is just an example of how to use this pattern, you can customize it according to the needs of your application.


# Data Persistence: DAO Pattern.

The DAO persistence pattern serves to isolate the persistence layer of the application layer, thus allowing both parts to evolve separately without knowing anything about the other.

### Structures

{% code title="Structures" %}

```
└── src
    └── main
        └── java
            └── com.your_company_name.your_name_app
                .
                .
                .
                └── persistence
                    └──SampleDAO.java
```

{% endcode %}

You can see an example using DAO in TotalCross in the [SQLite documentation](https://app.gitbook.com/@totalcross/s/playbook/~/drafts/-Ld5U4zrEcGVLc5JZxHO/primary/learn-totalcross/how-to-store-data-sqlite#inserting-data-into-the-table)

## Referencies

* See more about DAO Pattern in [baeldung ](< https://www.baeldung.com/java-dao-pattern>)and [DevMedia](https://www.devmedia.com.br/dao-pattern-persistencia-de-dados-utilizando-o-padrao-dao/30999)


# Separation of concepts: What is the best way to create UI interfaces?

## Overview

To create the user interfaces there are two controls: Containers and Windows. Whatever you are drawing to be displayed to the user must be within one of those controls. In the next topics of this session we will understand what the function of each one is and what factors that make Containers or Windows are preferable in certain cases.

![](/files/-LdFDgap1EgYq5zbnY0K)

## Differences Between Containers and Windows

First let's understand what the main function of each one is:

### Definition

* **Container**: is a control **capable of containing other controls**. It is primarily a form of **organization**. To fully understand the attributes and methods of this control, access the Container documentation in the API session by clicking below:

{% content-ref url="/pages/-Ld48N2AXPKb2kveJuAV" %}
[Container](/master/documentation/apis/control/container)
{% endcontent-ref %}

* **Window**: é a control capable **of overlapping others**, creating an illusion of **depth**. In addition, *Windows is also containers*, as they can accommodate several components within them. Windows **allow animations**, while the pure container exchange does not. As an example, we have the [Sliding](https://totalcross.gitbook.io/playbook/components/sliding-window) and the [Material ](https://totalcross.gitbook.io/playbook/components/material-window)Window, which have more modern transition effects.

To fully understand which attributes and control methods, access the Windows documentation in the API session by clicking below:&#x20;

{% content-ref url="/pages/-Ld48Pn3SVJ\_BN8cROWS" %}
[Window](/master/documentation/apis/control/window)
{% endcontent-ref %}

### Which one to use?

How much is thought in a `MessageBox`, it is clear that it is a Window and not only a Container, since it does not occupy the entire screen.

In cases where Window occupies the entire screen, the difference between Window and Container becomes narrower. **A full screen window does not "delete" the screen underneath, it is still there**. Ithis means that the status of the "bottom" screen remains **unchanged**. In addition, execution locks in the `popup` until `unpop` occurs (Windows are modal by default).&#x20;

In the case of container hot-swap exchanges, the container that left the scene actually leaves the scene and may even be **deleted if no reference to it is retained.**

Now that you know the definition of each becomes easier to identify where they should be used.

## Best Practices

Opting for mixed approach is the best way to use UI controls well. For, as shown, using only Containers deprives you of having transition animations. Using only Windows can generate an overuse of resources (**especially memory**).

With the mixed approach, one searches for the *best of both worlds*. However, it is worth mentioning some extra points:

* It's common for programmers to create whole systems for more control. It is not impossible to have a system of BaseContainers that can have animations or make a Windows system that **is not** heavy when there are many overlapping screens.
* It is also important to take into account the **designer's vision**. Some applications do **not** need animated transitions or only use animated transitions. This kind of thing can help you decide which approach to use.
* Finally, there are also other options. Using `SideMenu` is a form of pre-ready screen management. Some applications use a full screen `TabbedContainer` and switch screens with side swipes or programmatically.&#x20;

In cases of Processes and Flows of the application are "BaseContainers", since there is no need to keep the other screens in the background (and in memory) then we use Container.

As for the internal screens of a stream, it makes sense to use Windows and other features like `Scroll` or `Tabbed Containers` to perform transitions and organizations. You can have several examples of organization of interfaces in [MaterialTemplates in github,](https://github.com/TotalCross/MaterialTemplates) where we created several interface templates following the recommendations of the [Material](https://material.io/tools/color/).

In this way, Windows is used for animations and screen transitions within a stream and uses BaseContainers to switch from one stream to another of the application.

Taking a practical example, our implementation of SideMenu uses Containers for each screen and uses a TopMenu to create the Menu itself, which appears overlapping the current screen.

In [TCSample](https://github.com/TotalCross/TCSample),many of the screens use the `Material Window` to create a "second screen" within the current screen.

## Navigating between interfaces

### Container

To call a Container, just use:

* `swap(new InitialScreen());` - If you are in the Main Window and want to call a Container, simply use the `swap()` command.
* `MainWindow.getMainWindow().Swap(new SecondScreen());` - If you are in a container or Window and want to call a Container just use the command.

### Window

To call a window, just use:&#x20;

* `.popup()` - The execution **stops** after the `popup()`command is executed.
* `.popupNonBlocking()` - the execution **continues** right after the popup command, even with the window still open.

### Other Ways

As we mentioned in the previous topic, you can use BaseContainers to exchange flows in the application, in this case we use the `show()` and `back()`.  See the example below:

{% code title="BaseContainer\_Sample" %}

```java
public class BaseContainer extends Container {

    protected static final Vector containerStack = new Vector(5);

    public void show() {
    	//containerStack.
        containerStack.push(this); // push ourself
        MainWindow.getMainWindow().swap(this);
    }

    public void back() {
        if (parent == null || getParentWindow() == Window.getTopMost()) {
            try {
                containerStack.pop();
                MainWindow.getMainWindow().swap((Container)containerStack.peek());
            } catch (ElementNotFoundException enfe) {
                MainWindow.exit(0);
            }
        }
    }
}

```

{% endcode %}

Another way to work with interface changes without losing the data of each is through the design pattern called **Singleton**, where you **will create a single object for which there is only one instance**. To delve deeper into this pattern, just click [here](https://www.devmedia.com.br/padrao-de-projeto-singleton-em-java/26392).

## References

* To better illustrate where each of them is used, you can download the [Nubank\_Sample project in GitHub.](https://github.com/totalcross/Nubank_Sample)
* Reading [JavaDoc ](https://rs.totalcross.com/doc/)can be very useful.


# Positioning

The positioning of controllers in a container or window in TotalCross is done very easily and practically and can be done in two ways

### Relative Positioning

{% content-ref url="/pages/-L\_mqy8KBQ7nY9gj47mQ" %}
[Relative Positioning](/master/documentation/guides/app-architecture/hbox-and-vbox)
{% endcontent-ref %}

### Manual Positioning

{% content-ref url="/pages/-L\_mr1s6G6LFyssyXoKQ" %}
[Manual Positioning](/master/documentation/guides/app-architecture/relative-positioning/manual-positioning)
{% endcontent-ref %}


# Manual Positioning

The controls can be added in the container and window and to accomplish this we have some constants defined in the Control class that will aid in the positioning of the controlers

### Positioning on screen

To position a controller on the screen, simply use the ADD method

{% code title="How to add a control on screen" %}

```java
public void initUI() {
   // control, Positioning on the x axis, Positioning on the y axis) 
    add( new Label("Add a label for this screen"), CENTER, CENTER);
}    
```

{% endcode %}

The add method has some Overloading&#x20;

{% code title="Overloading  add" %}

```
    add(control, x axis, y axis, width, length)
    add(control, x axis, y axis, int width, int length, relativeControl)
    add(control, x axis, y axis) 
    add(control, x axis, y axis, relativeControl)
```

{% endcode %}

{% hint style="info" %}
If no **relative control** is added in the method add, the relative control will be the last control added on the screen.

{% code title="How to add a control on screen" %}

```java
add( new Label("Add a label for this screen"), CENTER, CENTER, relativeControl);

```

{% endcode %}
{% endhint %}

### Positioning on the X axis&#x20;

| Constant   | Description                                                                              |
| ---------- | ---------------------------------------------------------------------------------------- |
| BEFORE     | allocates control to the left of the relative control                                    |
| CENTER     | Place the Control in the middle of the screen with respect to the x-axis                 |
| AFTER      | allocates control to the Rigth of the relative control                                   |
| LEFT       | Put the Control on the left                                                              |
| RIGHT      | Put the Control on the Rigth                                                             |
| SAME       | They hold the same position as the relative control                                      |
| CENTER\_OF | Allocates the control at the center of the relative control space relative to the x-axis |
| RIGHT\_OF  | Allocates the control at the right of the relative control space relative to the x-axis  |
| KEEP       | Maintain the same relative control position                                              |
| PARENTSIZE | Assigned container size to control                                                       |

### Positioning on the Y axis&#x20;

| Constant   | Description                                                                               |
| ---------- | ----------------------------------------------------------------------------------------- |
| BEFORE     | allocates control to the up of the relative control                                       |
| CENTER     | Place the Control in the middle of the screen with respect to the y-axis                  |
| AFTER      | allocates control to the bottom of the relative control                                   |
| TOP        | Put the Control on the top                                                                |
| BOTTOM     | Put the Control on the bottom                                                             |
| SAME       | They hold the same position as the relative control                                       |
| CENTER\_OF | Allocates the control at the center of the relative control space relative to the y-axis  |
| BOTTOM\_OF | Allocates the control at the  bottom of the relative control space relative to the y-axis |
| KEEP       | Maintain the same relative control position                                               |
| PARENTSIZE | Assigned container size to control                                                        |

### Position with DP

You can also position the control using DP. Just use the `UnitsConverter.toPixels()`

```java
public void initUI() {
        Label lbl1 = new Label("");
        lbl1.setBackColor(Color.RED);

        Label lbl2 = new Label("");
        lbl2.setBackColor(Color.GREEN);
        
        add(lbl1, CENTER, CENTER, WILL_RESIZE , PREFERRED);
        add(lbl2, UnitsConverter.toPixels(DP + 50), UnitsConverter.toPixels(DP + 400), SCREENSIZE, PREFERRED);
}
```

### Control size

| Constant      | Description                                                                                    |
| ------------- | ---------------------------------------------------------------------------------------------- |
| PREFERRED     | The ideal value for the control size is calculated                                             |
| SAME          | Same size as relative control                                                                  |
| FILL          | Fills the entire size of the control                                                           |
| FIT           | Fill the space until you find a control                                                        |
| KEEP          | Maintains the same relative control                                                            |
| WILL\_RESIZE  | Assigns the control space to the end of the screen                                             |
| SCREENSIZE    | Assigns control size equal to screen size                                                      |
| SCREENSIZEMIN | Adjusts the control to receive the smallest dimension between portrait mode and landscape mode |
| SCREENSIZEMAX | Adjusts the control to receive the largest dimension between portrait mode and landscape mode  |
| PARENTSIZE    | Assigned container size to control                                                             |
| PARENTSIZEMIN | Assigns the size of the smallest container to the control                                      |
| PARENTSIZEMAX | Assigns the size of the largest container to the control                                       |

{% hint style="info" %}
To achieve greater precision, it is possible to add and subtract values to the parameters passed in the size of the control
{% endhint %}

### Images

![](/files/-LeNkpdrNTHd0qhd8Ejv)

![](/files/-LeNksj4l-ZHfBI4wjbK)

![](/files/-LeSN-7JaW-Bud7L15RK)


# Relative Positioning

At totalcross, we have two layouts ready to help you set up your application: HBox and VBox. These layouts can be described as 2 boxes where you "stack" your components, be it with a certain space between them or just simply really stacked. Both these layouts are extensions of the LinearBox class. To use them is pretty simple, all you ned to do is instantiate one of them, set its mode and add your components inside.

### Hbox

This layout will group your components horizontally,&#x20;

{% code title="How to use HBox Layout" %}

```java
public void initUI() {
    HBox hBox = new HBox(HBox.LAYOUT_FILL, HBox.ALIGNMENT_STRETCH);

    for (int i = 0; i < 5; i++) {
        hBox.add(new Button(i+""));
    }
    add(hBox, LEFT, CENTER, FILL, PREFERRED);
}
```

{% endcode %}

![](/files/-LdMvXswt5cx3SaWleoJ)

### Vbox

This layout will group your controllers vertically

{% code title="How to use VBox layout" %}

```java
public void initUI() {
    VBox vBox = new VBox(VBox.LAYOUT_FILL, VBox.ALIGNMENT_STRETCH);
    
    for (int i = 0; i < 5; i++) {
        vBox.add(new Button(i + ""));
    }
    add(vBox, CENTER, TOP, DP + 50, FILL);
}

```

{% endcode %}

![](/files/-LdMx-LQvganmrz9LsD2)

## Attributes

| Type    | Name                            | <p></p><p>Description</p>                                                        |
| ------- | ------------------------------- | -------------------------------------------------------------------------------- |
| **int** | LinearBox.LAYOUT\_STACK\_CENTER | Organizes the elements around the center.                                        |
| **int** | LinearBox.LAYOUT\_DISTRIBUTE    | Distributes the elements along the width or height of the box.                   |
| **int** | LinearBox.LAYOUT\_FILL          | Distribute and scale each element to fill the entire width or height of the box. |
| **int** | LinearBox.ALIGNMENT\_LEFT       | Aligns each child along the left/top border.                                     |
| **int** | LinearBox.ALIGNMENT\_RIGHT      | Aligns each child along the right/bottom border.                                 |
| **int** | LinearBox.ALIGNMENT\_CENTER     | Centers each child object.                                                       |
| **int** | LinearBox.ALIGNMENT\_STRETCH    | Stretches each child object.                                                     |
| **int** | Hbox.LAYOUT\_STACK\_LEFT        | Organizes each element from left to right.                                       |
| **int** | Hbox.LAYOUT\_STACK\_RIGHT       | Organizes each element from right to left.                                       |
| **int** | Vbox.LAYOUT\_STACK\_TOP         | Organizes each element from top to bottom.                                       |
| **int** | Vbox.LAYOUT\_STACK\_BOTTOM      | Organizes each element from bottom to top.                                       |

## Methods

| Type     | Name                                                | Description                                                                                         |
| -------- | --------------------------------------------------- | --------------------------------------------------------------------------------------------------- |
| **void** | setInsets(int left, int right, int top, int bottom) | Sets the internal paddings of this component.                                                       |
| **void** | setLayout(int mode, int alignment)                  | Sets the layout mode and alignment of this component.                                               |
| **void** | suspendLayout()                                     | Suspends all layout operations from 'add' calls until a 'resumeLayout' call.                        |
| **void** | resumeLayout()                                      | Performs all queued layout operations and resumes the default layout behaviour of the 'add' method. |
| **void** | setSpacing(int spacing)                             | Sets the spacing between components.                                                                |


# Best practices to improve project maintenance

## Overview

There are a few recommended practices to improve the organization, maintenance, and performance, and consequently loading your application. Some of them are very basic, like creating a class apart to store the colors used in the application and other more complex as working with loading images that are pulled from an external bank. In this chapter we will learn about these recommendations.&#x20;

You can download the [Material Templates project](https://github.com/TotalCross/MaterialTemplates), which contains all the recommendations below.

![](/files/-LdFNljY4VPQ5BC5kSzN)

## Colors

In the development of any application it is essential to have a design to prototype the user interfaces. It turns out that when the developer takes these prototypes and starts to develop, it often ends up adding these colors in the UI classes themselves, which makes it difficult to maintain this code.&#x20;

{% hint style="info" %}
you will find free website recommendations for screen prototyping in the part of [references](https://totalcross.gitbook.io/playbook/guideline/colors-fonts-and-images#references) in the last topic of this chapter.&#x20;
{% endhint %}

Now let's say you have an update to your application and the background color of the APP has changed. If your project has 2 or 3 screens, is it relatively quick to change these colors but if it is a more robust design of 15 screens? The developer would have to quit by changing the background color 15 times.&#x20;

Thinking about this, TotalCross recommends that you create a class named Colors and create constants for each color that you will need to use in the application, and preferably with suggestive names such as BACKGROUND. The name of the constants must always be in upper case. Here is the standard suggested by TotalCross, feel free to adapt to the needs of your project.

{% code title="Colors.class" %}

```java
import totalcross.ui.gfx.Color;

public class Colors {
	// The entire color palette follows the default material selected by the
	// Material Color Tool:
	// https://material.io/tools/color/#!/?view.left=0&view.right=1

	// Primary Colors
	public static int PRIMARY = 0xD32F2F;
	public static int P_LIGHT = 0xFF6659;
	public static int P_DARK = 0x9A0007;

	// Secondary Colors
	public static int SECONDARY = 0xF44336;
	public static int S_LIGHT = 0xFF7961;
	public static int S_DARK = 0xBA000D;

	//Texts Colors
	public static int TEXT_ON_P = 0xFFFFFF;
	public static int TEXT_ON_P_LIGHT = 0x000000;
	public static int TEXT_ON_P_DARK = 0xFFFFFF;

	public static int TEXT_ON_S = 0x000000;
	public static int TEXT_ON_S_LIGHT = 0x000000;
	public static int TEXT_ON_S_DARK = 0xFFFFFF;

	
	// Backcolor samples colors
	public static int BACKGROUND_GRAY_01 = Color.getRGB(245, 245, 246);
	public static int BACKGROUND_GRAY_02 = Color.getRGB(225, 225, 226);
	public static int BACKGROUND_GRAY_03 = Color.getRGB(205, 205, 206);

	// Others
	public static int SOFT_PEACH = 0xE9E2E1;
	public static int GRAY = 0XC0C1E8;

}

```

{% endcode %}

The names we attributed to the contenders were not by chance but rather due to the Color [Material](https://blog.totalcross.com/en/material-o-layout-da-google/) standard. You can generate each of these colors and better understand this pattern through [Material Color Tools](https://material.io/tools/color/#!/). With this Material tool you select the primary and secondary color of your project and it already generates the application's color palette and font color. &#x20;

We also provide the source code for you to download and adapt for the project. Just click [here](https://github.com/TotalCross/MaterialTemplates).&#x20;

## Images

To facilitate code maintenance, it is also recommended that all images be instantiated in a separate class called Images and only be called in the interface classes.&#x20;

Images class example:

{% code title="Images.class" %}

```java
import totalcross.io.IOException;
import totalcross.ui.image.Image;
import totalcross.ui.image.ImageException;

public class Images {
	public static Image addperson, cart, ic_adaptive_launcher_shell_background_retang;

	private Images() {
	}

	public static void loadImages(int fmH) {
		try {
			addperson = new Image("images/addperson.png");
			cart = new Image("images/cart.png");
			ic_adaptive_launcher_shell_background_retang = new Image(
					"images/ic_adaptive_launcher_shell_background.png");
		} catch (ImageException | IOException e) {
			e.printStackTrace();
		}
	}
}
```

{% endcode %}

Using Images.class:

```java
	public void initUI() {
		Images.loadImages(fmH);
		ImageControl cart = new ImageControl(Images.cart);
		add(cart, LEFT, TOP, FILL, FILL);
	}
```

## Fonts

As with colors and images, it happens when we are going to edit the fonts and here the problem is even worse, because we still have to stick to the size of fonts, colors and type.

So we advised that before the developer can already take with Design all these details to pass through a class with everything custom, as in the example below:&#x20;

{% code title="Fonts" %}

```java
import totalcross.ui.font.Font;

public class Fonts {

	public static final int FONT_DEFAULT_SIZE = 12;

	public static Font latoMediumDefaultSize;
	public static Font latoMediumPlus1;
	public static Font latoMediumPlus2;
	public static Font latoMediumPlus4;
	public static Font latoMediumMinus1;
	public static Font latoMediumMinus2;
	public static Font latoMediumMinus4;

	public static Font latoBoldDefaultSize;
	public static Font latoBoldMinus1;
	public static Font latoBoldMinus2;
	public static Font latoBoldMinus4;
	public static Font latoBoldPlus1;
	public static Font latoBoldPlus2;
	public static Font latoBoldPlus4;
	public static Font latoBoldPlus6;
	public static Font latoBoldPlus8;

	public static Font latoLightDefaultSize;
	public static Font latoLightPlus1;
	public static Font latoLightPlus2;
	public static Font latoLightPlus4;
	public static Font latoLightPlus6;
	public static Font latoLightMinus1;
	public static Font latoLightMinus2;
	public static Font latoLightMinus4;

	public static Font latoRegularMinus5;
	public static Font latoRegularDefaultSize;

	static {

		// Lato Regular
		latoRegularDefaultSize = Font.getFont("Lato Regular", false, FONT_DEFAULT_SIZE);
		latoRegularMinus5 = latoRegularDefaultSize.adjustedBy(-5);

		// Lato Medium
		latoMediumDefaultSize = Font.getFont("Lato Medium", false, FONT_DEFAULT_SIZE);
		latoMediumPlus1 = latoMediumDefaultSize.adjustedBy(1);
		latoMediumPlus2 = latoMediumDefaultSize.adjustedBy(2);
		latoMediumPlus4 = latoMediumDefaultSize.adjustedBy(4);
		latoMediumMinus1 = latoMediumDefaultSize.adjustedBy(-1);
		latoMediumMinus2 = latoMediumDefaultSize.adjustedBy(-2);
		latoMediumMinus4 = latoMediumDefaultSize.adjustedBy(-4);
		// Lato Bold
		latoBoldDefaultSize = Font.getFont("Lato Bold", false, FONT_DEFAULT_SIZE);
		latoBoldPlus1 = latoMediumDefaultSize.adjustedBy(1);
		latoBoldPlus2 = latoMediumDefaultSize.adjustedBy(2);
		latoBoldPlus4 = latoMediumDefaultSize.adjustedBy(4);
		latoBoldPlus6 = latoMediumDefaultSize.adjustedBy(6);
		latoBoldPlus8 = latoMediumDefaultSize.adjustedBy(8);
		latoBoldMinus1 = latoMediumDefaultSize.adjustedBy(-1);
		latoBoldMinus2 = latoMediumDefaultSize.adjustedBy(-2);
		latoBoldMinus4 = latoMediumDefaultSize.adjustedBy(-4);
		// Lato Light
		latoLightDefaultSize = Font.getFont("Lato Light", false, FONT_DEFAULT_SIZE);
		latoLightPlus1 = latoLightDefaultSize.adjustedBy(1);
		latoLightPlus2 = latoLightDefaultSize.adjustedBy(2);
		latoLightPlus4 = latoLightDefaultSize.adjustedBy(4);
		latoLightPlus6 = latoLightDefaultSize.adjustedBy(6);
		latoLightMinus1 = latoLightDefaultSize.adjustedBy(-1);
		latoLightMinus2 = latoLightDefaultSize.adjustedBy(-2);
		latoLightMinus4 = latoLightDefaultSize.adjustedBy(-4);
	}
}
```

{% endcode %}

to apply this class:

```java
public void initUI() {
  Label lbl = new Label(txt);
  lbl.setFont(Fonts.latoMediumMinus2);
  lbl.setForeColor(Colors.WHITE);
  add(lbl, LEFT, BOTTOM);
}
```

{% hint style="success" %}
Another way would be to create an enum to stylize and only apply where you need it. To learn how to do it this way just click [here](https://totalcross.gitbook.io/playbook/guideline/suggested-design-patterns/builder).&#x20;
{% endhint %}

## Material Constants

The Material recommends a series of [size and spacing patterns](https://material.io/components/), so it is ideal to create a class within the useful package and assigning these patterns to the constants, as in the example below:&#x20;

{% code title="MaterialConstants" %}

```java
import totalcross.ui.Control;
import totalcross.util.UnitsConverter;

/**
 * Constants of positioning and components size to make it easier to maintain
 * the app.
 * 
 * @author brunoamuniz
 *
 */

public class MaterialConstants {

	public static final int BORDER_SPACING = UnitsConverter.toPixels(16 + Control.DP);

	public static final int COMPONENT_SPACING = UnitsConverter.toPixels(8 + Control.DP);

	public static final int FAB_SIZE = UnitsConverter.toPixels(56 + Control.DP);

	public static final int MINI_FAB_SIZE = UnitsConverter.toPixels(40 + Control.DP);

	public static final int EDIT_HEIGHT_NO_CAPTION = UnitsConverter.toPixels(40 + Control.DP);

	public static final int EDIT_HEIGHT = UnitsConverter.toPixels(52 + Control.DP);

	public static final int TABS_HEIGHT = UnitsConverter.toPixels(40 + Control.DP);

}
```

{% endcode %}

to apply this class:

```java
Button btn = new Button("Button");
add(btn, LEFT + MaterialConstants.BORDER_SPACING, AFTER + MaterialConstants.COMPONENT_SPACING,
				FILL - MaterialConstants.BORDER_SPACING, PREFERRED);
```

## References

* Screen prototyping tool - [Invision app](https://www.invisionapp.com/), [figma](https://www.figma.com/), [marvel app](https://marvelapp.com/) and [adobeXD](https://www.adobe.com/br/creativecloud.html?ef_id=Cj0KCQjwtr_mBRDeARIsALfBZA571eitMauX00tdmLL6ARRBAGWNYxk-hO-eTsRNi61SH1Y6RlO1y4EaArMwEALw_wcB:G:s\&gclid=Cj0KCQjwtr_mBRDeARIsALfBZA571eitMauX00tdmLL6ARRBAGWNYxk-hO-eTsRNi61SH1Y6RlO1y4EaArMwEALw_wcB\&mv=search\&s_kwcid=AL!3085!3!301784432823!b!!g!!adobe+creative\&sdid=KQPOT);
* To better illustrate where each of them is used, you can download the [Nubank\_Sample project in GitHub](https://github.com/totalcross/Nubank_Sample);
* Screen templates in standard Material Design made with totalcross - [Material Templates](https://github.com/TotalCross/MaterialTemplates) ;
* [Material Standards](https://material.io/design/components/).


# Device Simulator

## Overview

TotalCross has its own simulator to help you test and visualize the app before sending the app to the mobile device. **The simulator comes embedded with TotalCross SDK**, you don't need to download anything else besides the SDK or configurate your pom.xml.

The simulator is a Java application that allows you to run a TotalCross application over the installed JDK, providing you a quick way to run and test your app, for different screen sizes, resolutions and DP just changing a few parameter.

Some people think that running the application on the desktop under an IDE (such as Eclipse or Netbeans) will use the TotalCross virtual machine. This is not true: the actual virtual machine used is the one provided in the Java Development Kit installed (or java.exe) on the desktop.

## Running the simulator

To run the simulator, we recommend you to create a class with a main method like this:

```
public class YourAppApplication {
	public static void main(String[] args) {
		TotalCrossApplication.run(YourApp.class);
	}
}
```

{% hint style="info" %}
**YourApp.class** must extend MainWindow and must be the only MainWindow in your project&#x20;
{% endhint %}

Now, just run YourAppApplication like a regular Java application and the simulator will works fine =)

{% hint style="info" %}
**TotalCross Key**: Probably you will need a TotalCross Key to run your simulator. First time you open the simulator without the key as a parameter, the simulator will ask you the key and store it at your O.S. Also, take a look at the "/r" parameter
{% endhint %}

You may also pass arguments to the launcher to simulate different resolutions and styles, and have an idea of how your application is going to look like on a particular device.

The basic format for using the parameters is:

```
TotalCrossApplication.run(YourApp.class, "parameter1", "value", "parameter2", "value");
```

## Screen Sizes Parameters

The optional arguments can be any combination of the following (not case sensitive):

### **Screen resolution and color depth**

/scr x: sets the width and height.

```
// E.g.: If you need to simulate iPhone Xs Resolution you should do like this 
TotalCrossApplication.run(YourApp.class, "/scr", "1125x2436");
```

{% hint style="info" %}
You can simulate any screen size and resolution with TotalCross Simulator. You just need to search for the specific device that you want to simulate and use the **"/scr"** parameter to configure the resolution
{% endhint %}

### **Usage of DP**

Since TotalCross 5, the SDK supports Density-independent pixels (DP) for components positioning and size, following the [Material Design specs](https://material.io/design/).&#x20;

/scale <0.1 to 4>: scales the screen, magnifying the contents (if greater than 1) or shrinking (if between 0 and 1).

The right way to use this parameter and simulate iPhone Xs, for example, is shown below&#x20;

```

TotalCrossApplication.run(YourApp.class, "/scr", "1125x2436", "/scale", "0.33");
```

### **Font Size**

Devices with different resolutions must have different font sizes too. With this parameter you can simulate different font sizes together with scale and screen configurations.&#x20;

/fontSize  : set the default font size to the one passed as parameter

{% hint style="info" %}
**We strongly recommend** you to set a default font size to your application directly on your MainWindow. If you let the application uses the font configuration of the device, your app can experience some differences running on different devices. Take a look at the chapter "[Colors, Fonts & Images](https://totalcross.gitbook.io/playbook/guideline/colors-fonts-and-images)" for more details.
{% endhint %}

## **Other Parameters**

### **TotalCross Key**

* /r: you can provide your TotalCross key directly through this parameter

```
		TotalCrossApplication.run(YourApp.class, "/r", "YOUR TC KEY");
```

### **Color depth**

* /bpp 8: emulates 8 bits per pixel screens. (256 colors). No used anymore on modern devices.
* /bpp 16: emulates 16 bits per pixel screens. (64K colors).
* /bpp 24: emulates 24 bits per pixel screens. (16M colors).
* /bpp 32: emulates 32 bits per pixel screens. (16M colors without transparency).

### **User interface style**

* /uiStyle Flat: Flat user interface style.
* /uiStyle Flat: Flat user interface style.
* /uiStyle Android: Android user interface style.

#### **@Device characteristics**

* /penlessDevice: acts as a device that has no touch screen. Note that all currently supported devices have touch screen.
* /geofocus: uses geographical focus (also activates penlessDevice).
* /fingerTouch: simulates the use of fingers (since a finger is less precise than a pen, uses an algorithm to find the control near the finger and also activates drag and flick).
* /unmovableSip: specifies that the Soft Input Panel (SIP) is unmovable, and simulates the screen shift that’s made when an Edit or MultiEdit gains focus.
* /virtualKeyboard: specifies that the device does not have a physical keyboard (or it has but the keyboard is closed).

### **Others**

* /pos x,y: sets the opening position of the application.
* /dataPath : sets where the PDB and media files are stored. This is also the default path for Litebase table files.
* /cmdLine <...>: the rest of the arguments (except the last one) are passed as the command line to the application being launched.
* /showmousepos: shows the mouse position (only when running on JavaSE).

## Function Keys

When running the application, the emulator shows some function keys that can be used to emulate a device key.&#x20;

* F2 Take screenshot and save to current folder
* F6 opens the application menu
* F7 back (escape)
* F9 tests the screen rotation using the launcher &#x20;
* F11 opens the keyboard (or calendar) in an Edit field.

## Quick parameter guide in simulator

Possible Arguments (in any order and case insensitive). Default is marked as \*.

| Arguments                   | Definition                                                                                                                                                                                                  |
| --------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| /scr WIDTHxHEIGHT           | sets the width and heightException in thread "main"                                                                                                                                                         |
| /scr WIDTHxHEIGHTxBPP       | sets the width, height and bits per pixel (8, 16, 24 or 32)                                                                                                                                                 |
| /scr Win32                  | Windows 32 (same of /scr 240x320x24)                                                                                                                                                                        |
| /scr iPhone                 | iPhone (same of /scr 640x960x24)                                                                                                                                                                            |
| \*/scr android              | Android         (same of /scr 320x568x24)                                                                                                                                                                   |
| /pos x,y                    | Sets the openning position of the application                                                                                                                                                               |
| /uiStyle Flat               | Flat user interface style                                                                                                                                                                                   |
| \*/uiStyle Vista            | Vista user interface style                                                                                                                                                                                  |
| /uiStyle Android            | Android 4 user interface style                                                                                                                                                                              |
| /uiStyle Holo               | Android 5 user interface style                                                                                                                                                                              |
| /uiStyle Material:          | Material 6 user interface style                                                                                                                                                                             |
| /penlessDevice              | acts as a device that has no touchscreen                                                                                                                                                                    |
| /fingerTouch                | acts as a device that uses a finger instead of a pen                                                                                                                                                        |
| <p>/unmovablesip</p><p></p> | acts as a device whose SIP is unmovable (like in Android and iPhone).                                                                                                                                       |
| /geofocus                   | enables geographical focus.                                                                                                                                                                                 |
| /virtualKeyboard            | shows the virtual keyboard when in an Edit or a MultiEdit                                                                                                                                                   |
| /showmousepos               | shows the mouse position.                                                                                                                                                                                   |
| /bpp 8                      | emulates 8 bits per pixel screens (256 colors)                                                                                                                                                              |
| /bpp 16                     | emulates 16 bits per pixel screens (64K colors)                                                                                                                                                             |
| /bpp 24                     | emulates 24 bits per pixel screens (16M colors)                                                                                                                                                             |
| /bpp 32                     | emulates 32 bits per pixel screens (16M colors without transparency)                                                                                                                                        |
| /scale                      | scales the screen, magnifying the contents using a smooth scale.                                                                                                                                            |
| /fastscale                  | scales the screen, magnifying the contents using a fast scale.                                                                                                                                              |
| /dataPath                   | sets where the PDB and media files are stored                                                                                                                                                               |
| /cmdLine <...>              | the rest of arguments-1 are passed as the command line                                                                                                                                                      |
| /fontSize                   | set the default font size to the one passed as parameter                                                                                                                                                    |
| /r                          | specify a registration key to be used to activate TotalCross when required. You may use %key%, where key is an environment variable The class name that extends MainWindow must always be the last argument |

## Another way to run the simulator

Another way to run the simulator is calling the **totalcross.Launcher** class directly through the command line or "Run" from Eclipse IDE like the images below

![](/files/-LbPFcWPD26BnzQUtIJ9)

![](/files/-LbPFkvQwmycxsBHeiYR)

The results will be exactly the same in both ways. You can choose which one is the best for you.


# Package your app from scratch

## **Requirements**

This guide is intended for devs who have gone through get started or have knowledge of:

* [**TotalCross SDK**](http://www.superwaba.net/SDKRegistrationService/)**;**
* [**Environment variables configured**](https://app.gitbook.com/@totalcross/s/playbook/learn-totalcross/getting-started/environment-configuration)**;**
* [**JDK installed**](/master/documentation/miscelaneous/java-8)**.**

## Deploy

You can do deploy to Android, iOS e Windows with **Maven** or by **Command Line**

{% tabs %}
{% tab title="Maven" %}

#### Pom File

Make sure your pom file has the **build tag, dependencies tag, repositories tag and properties tag** as shown below

```markup
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>

    <groupId>com.totalcross</groupId>
    <artifactId>HelloWorld</artifactId>
    <version>1.0-SNAPSHOT</version>
    <name>HelloWorld</name>

    <properties>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
        <totalcross.activation_key>PLACE_YOUR_KEY</totalcross.activation_key>
    </properties>

    <dependencies>
        <dependency>
            <groupId>com.totalcross</groupId>
            <artifactId>totalcross-sdk</artifactId>
            <version>6.0.3</version>
        </dependency>
    </dependencies>

    <repositories>
        <repository>
            <id>totalcross-repo</id>
            <name>ip-172-31-40-140-releases</name>
            <url>http://maven.totalcross.com/artifactory/repo1</url>
        </repository>
    </repositories>

    <pluginRepositories>
        <pluginRepository>
            <id>totalcross-repo</id>
            <name>ip-172-31-40-140-releases</name>
            <url>http://maven.totalcross.com/artifactory/repo1</url>
        </pluginRepository>
    </pluginRepositories>

    <build>
        <finalName>${project.artifactId}</finalName>
        <plugins>
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-compiler-plugin</artifactId>
                <version>3.1</version>
                <configuration>
                    <source>1.8</source>
                    <target>1.8</target>
                </configuration>
            </plugin>
            <plugin>
                <groupId>com.totalcross</groupId>
                <artifactId>totalcross-maven-plugin</artifactId>
                <version>1.0</version>
                <configuration>
                    <name>${project.name}</name>
                    <platforms>
                        <platform>-win32</platform>
                        <platform>-android</platform>
                        <platform>-ios</platform>
                    </platforms>
                    <activationKey>${totalcross.activation_key}</activationKey>
                    <!--                    For version 4.4.2 and 5.1.4 or later, Apple certificates are no longer required. -->
                    <!--                    <certificates>${totalcross.applecertificate}</certificates>-->
                    <!--                    <totalcrossHome>/Users/italo/TotalCross5</totalcrossHome>-->
                </configuration>
                <executions>
                    <execution>
                        <id>post-package</id>
                        <phase>package</phase>
                        <goals>
                            <goal>package</goal>
                        </goals>
                    </execution>
                </executions>
            </plugin>
        </plugins>
    </build>
</project>
```

Inside the **platfrom tag** you can add the argument:

#### Argument for plataforms to deploy

* `<platform>-win32</platform>`This platform is used to build for **Windows**;
* `<platform>-wince</platform>`This platform is used to build for **Windows CE**;
* `<platform>-winmo</platform>`This platform is used to build for **Windows Mobile Only;**
* `<platform>-linux</platform>`This platform is used to build for **Linux x86 (Debian);**
* `<platform>-linux_arm</platform>`This platform is used to build for **Linux ARM**;
* `<platform>-applet</platform>`Create the html file and a jar file with all dependencies  &#x20;to run the app from a java-enabled browser (the input cannot be a jar file);
* `<platform>-ios</platform>`This platform is used to build for **IOS**;
* `<platform>-android</platform>`This platform is used to build for **Android**;
* `<platform>-all</platform>`Single parameter to deploy to all supported platforms;

#### Options

* `<platform>/p</platfrom>`Package the **VM** with the application;
* `<platform>/r</platform>`Specify a **registration key** to be used to activate TotalCross when required;
* `<platform>/m</platform>`**Specifies a path** to the mobileprovision and **certificate store** to deploy an ipa file for iOS;
* `<platform>/a</platform>`Assigns the application id; can only be used for libraries or passing a .tcz file;
* `<platform>/autostart</platform>`automatically starts the application after a boot is completed. Currently works for Android only;
* `<platform>/c</platform>`Specify a command line to be passed to the application;
* `<platform>/i</platform>`Install the file after generating it; platforms is a list of comma-separated platforms. Supports: android. E.G.: /i android;
* `<platform>/k</platform>`Keep the .exe and other temporary files during wince generation;
* `<platform>/kn</platform>`As /k, but does not create the cab files for WinCE;
* `<platform>/n</platform>`Override the name of the tcz file with the given name;
* `<platform>/o</platform>` Override the output folder with the given path (defaults to the current folder);
* `<platform>/t</platform>`Just test the classes to see if there are any invalid references. Images are not converted, and nothing is written to disk;
* `<platform>/v</platform>`Verbose output for information messages;
* `<platform>/w</platform>`Waits for a key press if an error occurs;
* `<platform>/x</platform>`Comma-separated list of class names that must be excluded (in a starts-with manner). E.G.: "/x com/framework/".

#### Build your app

To deploy your application you only need to use a maven execution template by passing the command:`mvn package`
{% endtab %}

{% tab title="Command Line" %}
To deploy by command line you need to be in the folder that contains the jar of your project and pass the parameters of tc.Deploy:

#### Argument for plataforms to deploy

* `-win32`This argument is used to build for **Windows**;
* `-wince`This argument is used to build for **Windows CE**
* `-winmo` This argument is used to build for **Windows Mobile Only;**
* `-linux` This argument is used to build for **Linux x86 (Debian)**;
* `-linux_arm` This platform is used to build for **Linux ARM**;
* `-applet` the html file and a jar file with all dependencies to run the app from a java-enabled browser (the input cannot be a jar file);
* `-ios`This argument is to build for **iOS**;
* `-android`This argument is to build for **Android**;
* `-all`Single parameter to deploy to all supported platforms;

#### Options

* `/p`Package the **VM** with the application;
* `/r`Specify a **registration key** to be used to activate TotalCross when required;
* `/m`**Specifies a path** to the mobileprovision and **certificate store** to deploy an ipa file for iOS;
* `/a`Assigns the application id; can only be used for libraries or passing a .tcz file;
* `/autostart`automatically starts the application after a boot is completed. Currently works for Android only;
* `/c` Specify a command line to be passed to the application;
* `/i`install the file after generating it; platforms is a list of comma-separated platforms. Supports: android. E.G.: /i android;
* `/k`Keep the .exe and other temporary files during WinCE generation;
* `/kn`As /k, but does not create the cab files for WinCE;
* `/n` Override the name of the .tcz file with the given name;
* `/o` Override the output folder with the given path (defaults to the current folder);
* `/t` Just test the classes to see if there are any invalid references. Images are not converted, and nothing is written to disk;
* `/v`Verbose output for information messages;
* `/w` Waits for a key press if an error occurs;
* `/x`Comma-separated list of class names that must be excluded (in a starts-with manner). E.G.: "/x com/framework/".

#### See the example below

`java -cp "%TOTALCROSS3_HOME%"/dist/totalcross-sdk.jar tc.Deploy HelloTC.jar -android /p /r YOUR_TC_KEY_HERE`

`"%TOTALCROSS3_HOME%"`  is the folder where the TC SDK

`HelloTC.jar` is the .jar of project
{% endtab %}
{% endtabs %}

## Your apps

After packaging your application the files will be in the `project_folder\target\install\`

{% hint style="danger" %}
Problems with WinCE? If your Operational System is not Windows or it is Windows and has not Cabwiz program, try to add`/k`as first platform to  in your pom.xml
{% endhint %}


# TotalCross SDK

{% hint style="warning" %}
**Make sure you have the** [**Java SE Development Kit (JDK)**](https://app.gitbook.com/@totalcross/s/playbook/learn-totalcross/getting-started/basic-requirements#install-java-se-development-kit-jdk) **installed.**
{% endhint %}

### Download SDK

**Access this**[ **website**](http://www.superwaba.net/SDKRegistrationService/)

[![](https://lh4.googleusercontent.com/XGDkS9ckDHTInGeZVCKPC1aSwdqqUFE0uc84WrCyYdakYZ793u0j8krhfqp0hAZZHRKoL6T-D76S2uvrzkaP4YS7gMKP7SpPPrU_2t_ideor-ZYqJXy23icMKkSH8JI4qqX6-7LG)](http://www.superwaba.net/SDKRegistrationService/)

**After logging into the website, you can download TC SDK**

![](https://lh5.googleusercontent.com/-wzvsRGNjvCtEvheiHjY-9NXxQAaUQ5yAmc4ne7wMb_lxkMoWzZ71797s45gdRnboICn3l9VouXFLUECIY4wkj7kpBI-duHcWEhVTu9VAE95sPTZptQkO1zTkKQUu96mPqfOETFe)

**Download the .zip version of TotalCross SDK and put in** <br>


# Environment Variables in IDE

As you may have seen in the [Deploy session](https://totalcross.gitbook.io/playbook/learn-totalcross/deploy-your-app-android-ios-and-windows), in the basic requirements part, you need the TotalCross SDK to generate your application (apk, ipa, exe and etc).

{% hint style="info" %}
**Remember**: This happens because at the time of generating your application for the desired platform it is necessary to pass all your code through our virtual machine (TCVM).
{% endhint %}

To point to the SDK, you can either configure this environment variable in the operating system itself or it can point directly to the IDE (depending on which one you are using).

Because it is much easier to configure the SDK directly in the IDE we chose to create a step-by-step guide on how to configure your IDE at the time of deployment and point to the TotalCross SDK.

### IDEs

* [Eclipse](https://totalcross.gitbook.io/playbook/learn-totalcross/environment-configuration/eclipse)
* [IntelliJ](https://totalcross.gitbook.io/playbook/learn-totalcross/environment-configuration/intellij)
* [NetBeans](https://totalcross.gitbook.io/playbook/learn-totalcross/environment-configuration/netbeans)
* [Visual Studio Code](https://totalcross.gitbook.io/playbook/learn-totalcross/environment-configuration/visual-studio-code)


# Eclipse

## Configuring Environment Variable in Eclipse

To set the **TOTALCROSS3\_HOME** (environment variable that points to the Totalcross SDK) in Eclipse is pretty simple, as you can see below:

### Step 1: Run Settings

There are two ways to get to the "Run Configurations" option in Eclipse:

* First, just right-click on **your project** and go to "**run as**" and then click "**Run Configurations**";

![1. Run Configurations](/files/-LcBpJP-wPsrcM_SkU_6)

* The second way is to click on the **green symbol** with the white button inside the **top bar** of the eclipse and then click on "**Run Configurations**".

![2. Run Configurations](/files/-LcBq3TBumW4ZH3kZ0fC)

### Step 2: Maven Build

1. Now just go into **Maven Build** and double-click to open a **new configuration**;
2. Click the "**Environment**" tab and click the "**New**" button;
3. In the **name** write "**TOTALCROSS\_HOME**" and in values ​​put the **path to the TotalCross SDK on your machine** and then click "OK" and then "Apply.". Look at an image below:

![](/files/-LcBrSeajtcxESC8p_AC)

{% hint style="warning" %}
But it is worth mentioning, if the other steps to implement the files have already been completed (such as a configuration of pom.xml, sdk being installed and etc) you will **not** be able to get the [deploy](https://totalcross.gitbook.io/playbook/learn-totalcross/deploy-your-app-android-ios-and-windows).&#x20;
{% endhint %}


# IntelliJ

## Configuring Environment Variable in IntelliJ

To set the **TOTALCROSS3\_HOME** (environment variable that points to the Totalcross SDK) in Eclipse is pretty simple, as you can see below:

### Step 1: Run Settings

1. With your Maven project open, you will click on the "**Run**" option on the **top bar** of IntelliJ
2. Under Download, click "**Edit Configurations"**
3. Click "**Templates**" and then "**Maven**"

![](/files/-LcCZiynMjSljTf8iyeK)

### Step 2: Maven  Configuration

1. Click the "**Runner**" tab
2. **Uncheck** "Use project settings"
3. In the "Environment Variables" option you click on the **folder icon**
4. Click the "**+**" symbol to the right of the window.
5. In the Name field you fill in with "**TOTALCROSS3\_HOME**" and in the Value field you **fill in the path to a folder containing the TotalCross SDK**, then click "OK" and then "Apply."

![Templates > Maven > Runner > Enviroment Variables > + >](/files/-LcC_Rgs_IiS-yMq_qCF)

{% hint style="warning" %}
But it is worth mentioning, if the other steps to implement the files have already been completed (such as a configuration of pom.xml, sdk being installed and etc) you will **not** be able to get the [deploy](https://totalcross.gitbook.io/playbook/learn-totalcross/deploy-your-app-android-ios-and-windows).&#x20;
{% endhint %}


# Deploy your app with a dependecy TC

In this tutorial we will use the repository <https://github.com/TotalCross/tc-utilities>

## Download Dependecy

‌You need to add in your pom file within your dependencies tag the dependency:

{% code title="Dependecy Example" %}

```
<dependencies>
    .
    .
    .
    <dependency>
        <groupId>com.totalcross.utils</groupId>
        <artifactId>tc-utilities</artifactId>
        <version>0.0.1-SNAPSHOT</version>
    </dependency>
    
</dependencies>
```

{% endcode %}

## Generate TCZ

After downloading the dependency it will be necessary to generate the tcz of the dependency so that it is included in the deploy

Find the folder you extracted the project from or if you have downloaded it by pom that is located in the dependency, usually is: C:\Users\\**your\_user**\\.m2\repository\com\totalcross\utils\tc-utilities\0.0.1-SNAPSHOT.

![](https://blobscdn.gitbook.com/v0/b/gitbook-28427.appspot.com/o/assets%2F-L_mPP3a_E_A7NbRMq7Q%2F-Ler5cEPPNSBJ9P-W-mI%2F-Ler7XyzuHa5LexKKFId%2FPasta.PNG?alt=media\&token=a45e3908-5361-4bca-adb5-fc79b3590c54)

To generate tcz execute the command java -cp "% TOTALCROSS 3\_HOME%" / dist / totalcross-sdk.jar tc.Deploy tc-utilities-0.0.1-SNAPSHOT.jar / r YOUR\_TC\_KEY‌

![](https://blobscdn.gitbook.com/v0/b/gitbook-28427.appspot.com/o/assets%2F-L_mPP3a_E_A7NbRMq7Q%2F-LerIfBrCEJKzx7OT0xZ%2F-LerIl475Yrmu5dtoeFU%2FComp.PNG?alt=media\&token=b491c16a-dba7-4c53-8e68-16c90e5e2a50)

After tcz is generated, rename the tc-utilities-0.0.1-SNAPSHOT.tcz file to tc-utilities-0.0.1-SNAPSHOTLib.tcz and place it at the root of the project.‌

At the root of the project create the file named **all.pkg** and put \[L] tc-utilities-0.0.1-SNAPSHOTLib.tcz so that this class is included in deploy

![](https://blobscdn.gitbook.com/v0/b/gitbook-28427.appspot.com/o/assets%2F-L_mPP3a_E_A7NbRMq7Q%2F-Ler5cEPPNSBJ9P-W-mI%2F-LerEHwNAfZIsaPx7r-N%2F1.1.png?alt=media\&token=4b4ad9a8-3f97-494e-89e1-46f16db4172e)


# Deploy iOS

### Generating key store and certificate

#### You need to have openssl installed in your computer.

* If you use Mac OS, this should be installed as default
* If you use Linux, we recomend to install your distro binaries
* If you use Windows, you should install OpenSSL for Windows
* If you use Windows, you may install a git-bash (like the one embedded within SourceTree)

First, you need to create your RSA 2048 key-pair with the following command:

&#x20;`openssl req -nodes -newkey rsa:2048 -keyout request.key -out request.csr`

You will be prompted with some questions, which you need to supply the answers. You may want to configure the `openssl req` with predefined data. To do so, create a `config` file like the template below:

```
[ req ]
distinguished_name = req_distinguished_name
prompt = no
[ req_distinguished_name ]
emailAddress = john@webmail.com
commonName = John Doe
countryName = BR
stateOrProvinceName = Rio de Janeiro
localityName = Rio de Janeiro
organizationName = John’s Company
```

Then pass it to the `openssl req` command like the follow:

```
openssl req -config config -nodes -newkey rsa:2048 -keyout request.key -out request.csr
```

{% hint style="info" %}
Optionally, you can call openssl without passing a config file using the interactive mode.

```
openssl req -nodes -newkey rsa:2048 -keyout request.key -out request.csr
```

{% endhint %}

* &#x20;`request.key` is the private key
* &#x20;`request.csr` is the public key

Never share your private key `request.key` in a non-secure media. If you must transfer it from your trusted computer to another, do it safely. Some suggestions are:

1. use `scp` to copy this file over `ssh` encryption to your other trusted computer;
2. zip it with a password, forward the file with a pen-drive or in a email, and tell the destinatary the password through another media;
3. upload it with `https` to a trusted server of your own.

If somehow you have shared your private key `request.key` in a unsecure way, please, **BURN IT WITH FIRE BEFORE IT LAYS EGGS OF SECURITY BREACHNESS**. You are warned. You should take your security seriously. Pretty pretty seriously.

Your public key is meant to be shared with the wind. There is no worry about this as long as[P≠NPP \neq NPP̸​=NP](https://en.wikipedia.org/wiki/P_versus_NP_problem).

Now go to the [Apple Developer Page](https://developer.apple.com/account/ios/certificate/) and request a new certificate. Choose accordingly to your needs.

### Creating your certificate

You should now see this screen:

![](/files/-Lnn4uqiV-GzgwMiRx_e)

As I need a production certificate for an Enterprise account, I choosed the `In-House and Ad-Hoc`.&#x20;

&#x20;And then finally to the screen where I now shall upload the generated `.csr`file (it is the public key, so therefore no worry):

![](/files/-Lnn5DV3Sn8g911TN_IV)

Now you can download the certificate at any time. This file is commonly named as `ios_distribution.cer`.

### iOS App ID

To generate the provisioning profile, one must have before-hand to register new Apple ID in `Register a new Identifier`:

![](/files/-Lnn5bTPs07v1YEcvXab)

![](/files/-LnrO0mklBS4zwl0Tc-B)

&#x20;In the sample above, I have choosen to go with the `Explicit App ID`, `com.totalcross.tcguide`.&#x20;

{% hint style="warning" %}
You cannot enable **Push Notification** service using **Wildcard Apple ID**.
{% endhint %}

{% hint style="danger" %}
You shall not use **Wildcard Apple ID** if you want to distribute your application with **Enterprise Distribution**. This may leads to trouble when your client tries to upgrade the app you have provided.
{% endhint %}

&#x20;

### Provisioning profile

Now we must generate the provisioning profile:

![](/files/-LiFiTk36FEi8YLsoG-7)

As I want an enterprise distribution, I must choose the `In-House` provisioning profile:

{% hint style="info" %}
If you want to test your app in specific iOS devices, you must create a `Development` provisioning file. To do so follow the tutorial: [Using Development certificate to test your application.](/master/documentation/guides/package-your-app-from-scratch/deploy-ios/using-development-certificate-to-test-your-apps)
{% endhint %}

![](/files/-LnnF7Az7kRkjTjUpKlo)

Now the system will ask you about the App ID, then the certificate, and finally you are prompted with a Profile Name. It can be arbitrary:

You end this step downloading a `.mobileprovision` file.

### Recalling

You have created in your own machine this files:

* &#x20;`config (optional)`, so that it will be easy to create your public/private keys
* &#x20;`request.key`, your private key
* &#x20;`request.csr`, your public key
* &#x20;`ios_distribution.cer`, your Apple certificate
* &#x20;`.mobileprovision`, one of the most important files so that you can indeed embed this in your app to distribute

### Finishing the basis to compile to iOS with TotalCross

So far, so good. Now we need to create a Publc-Key Cryptography Standard 12 `.p12` file. To create it, we need the intermediary container for public key `.pem` file.

> [This question](https://serverfault.com/q/9708) in ServerFault gives you more details about the files format. Also it was where I got that information above.

To create the `.pem` file, just give this command:

```
openssl x509 -in ios_distribution.cer -inform DER -out ios_distribution.pem -outform PEM
```

Where:

* &#x20;`x509`\
  &#x20;is the cryptography standard
* &#x20;`-in ios_distribution.cer`\
  &#x20;indicates that the input certificate file is named `ios_distribution.cer`
* &#x20;`-inform DER`\
  &#x20;indicates that the format of the input file is `DER`, so that OpenSSL can do its conversion\
  &#x20;AKA *translate from `DER`*
* &#x20;`-out ios_distribution.pem`\
  &#x20;indicates that the output file name is named `ios_distribution.pem`
* &#x20;`-outform PEM`\
  &#x20;indicates that the output format is `PEM`\
  &#x20;AKA *translate to `PEM`*

With the `.pem` file created, we just need to create the `.p12` file:

```
openssl pkcs12 -export -inkey request.key -in ios_distribution.pem -out ios_distribution.p12
```

Where:

* &#x20;`pkcs12`\
  &#x20;is the cryptography standard
* `-export`
* &#x20;`-inkey request.key`\
  &#x20;which file is the private key? It is `request.key`
* &#x20;`-in ios_distribution.pem`\
  &#x20;which file is the container for your certificate? `ios_distribution.pem`
* &#x20;`-out ios_distribution.p12`\
  &#x20;which file I want to save as my PKCS 12 file? `ios_distribution.p12`

{% hint style="warning" %}
**For TotalCross SDK 4.4.1 or earlier and 5.1.3 or earlier:**

You must create two **.p12 files**. The first one **with password** to be added in your keychain (you can name it ios\_distribution\_with\_password.p12). The second one **without password** to be used in your **tc.Deploy** through the `/m` parameter.

**For later versions:**

You can create just one **.p12 file with password**  to be added in your keychain. For later versions, we no longer require parameter /m (Deprecated) to build your TotalCross ipa.
{% endhint %}

### Adding your certificate to your Keychain in your macOS

{% hint style="warning" %}
Requires a **p12 file with password**.
{% endhint %}

Click twice in p12 file. A box with password field will be shown, type your p12 file password in the **field passwor**d and your certificate will be added to your macOS Keychain.

![](/files/-LnrNwXekkgWOewev7xd)

### iOS deployments

#### GENERATING YOUR IPA FILE BY USING TOTALCROSS DEPLOYER

{% hint style="warning" %}
**For TotalCross SDK 4.4.1 or earlier and 5.1.3 or earlier:**

Before executing the following steps, copy your certificate file, `ios_certificate.p12`, and your mobileprovision file, `profile.mobileprovision,` to a separate folder inside workspace directory.
{% endhint %}

#### Maven

Execute command `mvn package` using the following pom.xml as example:

```markup
<properties>
		<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
		<totalcross.activation_key>place holder</totalcross.activation_key>
</properties>
	
<build>
		<finalName>${project.artifactId}</finalName>
		<plugins>
			<plugin>
				<groupId>org.apache.maven.plugins</groupId>
				<artifactId>maven-compiler-plugin</artifactId>
				<version>3.1</version>
				<configuration>
					<source>1.8</source>
					<target>1.8</target>
				</configuration>
			</plugin>
			<plugin>
				<groupId>net.orfjackal.retrolambda</groupId>
				<artifactId>retrolambda-maven-plugin</artifactId>
				<version>2.5.6</version>
				<executions>
					<execution>
						<goals>
							<goal>process-main</goal>
							<goal>process-test</goal>
						</goals>
					</execution>
				</executions>
			</plugin>
			<plugin>
				<groupId>org.codehaus.mojo</groupId>
				<artifactId>exec-maven-plugin</artifactId>
				<version>1.1.1</version>
				<executions>
					<execution>
						<phase>package</phase>
						<goals>
							<goal>java</goal>
						</goals>
						<configuration>
							<mainClass>tc.Deploy</mainClass>
							<arguments>
								<argument>${project.build.directory}/${project.build.finalName}.${project.packaging}</argument>
								<argument>-ios</argument>
								<argument>/p</argument>
								<argument>/r</argument>
								<argument>${totalcross.activation_key}</argument>
								<!-- 
									Parameter /m is just required for versions 4.4.1 or ealier
									and 5.1.3 or ealier.
								 -->
								<argument>/m</argument>
								<argument>{put ios certificate path here}</argument>
							</arguments>
						</configuration>
					</execution>
				</executions>
			</plugin>
		</plugins>
	</build>
```

#### Old style command line

If you rather the old style way of deploying:

`java -cp "%TOTALCROSS3_HOME%"/dist/totalcross-sdk.jar tc.Deploy HelloTC.jar -iphone /m ./ios_certs /p /r YOUR_KEY_HERE`

`"%TOTALCROSS3_HOME%" = is the folder where the TC SDK`

`HelloTC.jar = is the jar of project`

`ios_certs = path to certificate`

#### RESIGNING YOUR APPLICATION

> Requirements:
>
> 1. having XCode updated to version `>=10.0`
> 2. having **Imagemagick** installed
> 3. having Totalcross SDK `>=4.2.1` installed
> 4. having your certificate shown in the list of valid identities returned by executing `security find-identity`:
>
> ```
> $ security find-identity
>
> Policy: X.509 Basic
>   Matching identities
>   1) XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX "iPhone Distribution: Your Company"
>   2) XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX "iPhone Distribution: Your Company 2"
>   3) XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX "iPhone Developer: Your Name"
>   4) XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX "iPhone Distribution: Your Company 3"
>
>   Valid identities only
>   1) XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX "iPhone Developer: Your Name"
>   2) XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX "iPhone Distribution: Your Company 3"
>      2 valid identities found
> ```

#### &#x20;Preparing environment

1. Install **Imagemagick** by entering command (if you don't have brew installed visit [this page](https://brew.sh/) and install it. Its pretty easy!):

> ```
> brew install imagemagick
> ```

1. Switch Command Line Developer Tools to CLT XCode directory by executing

> ```
> sudo xcode-select --switch /Applications/Xcode.app/Contents/Developer
> ```

1. Give execution permission to the sh scripts inside `path/to/your/totalcross_sdk_home/etc/tools/iOSCodesign`

> ```
> sudo chmod +x tccodesign.sh xcassetsGenerator.sh
> ```

#### &#x20;Resigning your app.ipa

> Artifacts needed for this step:
>
> 1. the TotalCross generated `.ipa`
> 2. your provisioning profile
> 3. your Certificate name (`iPhone Distribution: Your Company`)
> 4. Method, which can be: app-store, ad-hoc, enterprise or development. (It must match your .mobileprovision type)
> 5. Your Application Icon
> 6. a Mac OS X computer

Having all of those parameters, you will be able to run the following command:

```
./tccodesign --ipa path/to/to-be-signed.ipa --icon path/to/icon.png --provision-file path/to/provision-file.mobileprovision --certificate 'iPhone Distribution: XXXX Company YYYYY' -m [ad-hoc | app-store | enterprise | development]
```

| Parameters              | Description                                                                                                                                                                                     |
| ----------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| --ipa, -i               | Represents the path to your ipa file  generated by the tc.Deployer that you want to be resigned.                                                                                                |
| --icon                  | Represents the path to your application icon. If you ommit it, the totalcross icon will be placed.                                                                                              |
| --provision-file, -prov | Represents the path your mobileprovision file.                                                                                                                                                  |
| --certificate, -c       | Represents the name of your certificate as shown in your mac keychain (you may copy this name from the keychain or from the command `security find-identity` in the list of valid certificates. |
| --method, -m            | <p>Represents the method which you want to distribute your app. They are:</p><ul><li>ad-hoc;</li><li>app-store;</li><li>enterprise;</li><li>development.</li></ul>                              |
| --output, -o (optional) | Represents the path in which your resigned ipa file will be placed. If you ommit this parameters, your resgined ipa file will be generated inside`[tccodesign.sh directory]/build`              |

{% hint style="success" %}
Now you're ready to properly install or upload to the apple store your application.
{% endhint %}


# Using Development certificate to test your apps

In order to test your application file you must resign your application using a Development Certificate and a `mobileprovision` file for development. To do so, create a Development Certificate in the same way you have created your Distribution one ([Creating certificate](https://app.gitbook.com/@totalcross/s/playbook/~/drafts/-Lnn-qXXBj5lBCqiQBQ-/primary/learn-totalcross/deploy-your-app-android-ios-and-windows/deploy-ios#creating-your-certificate)) and a Development mobileprovision ([Provisioning file](https://app.gitbook.com/@totalcross/s/playbook/~/drafts/-Lnn-qXXBj5lBCqiQBQ-/primary/learn-totalcross/deploy-your-app-android-ios-and-windows/deploy-ios#provisioning-profile)).&#x20;

### Adding devices to your mobileprovision

{% hint style="warning" %}
Applications resigned for development only works on devices registred in the [Apple Developer website](https://developer.apple.com) and in your `mobileprovision`.
{% endhint %}

First of all, resgistering your device in the Apple Developer website requires you to know your apple device UDID. To retrieve it, follow the steps bellow:

1- Connect your device through a **USB** **port** to a computer running **macOS** or **Windows**.

2- Open the [iTunes](https://www.apple.com/br/itunes/) application. You're going to see a smartphone icon on the top left side of the application. Click on it!

![](/files/-Lnt--6XA9djhWbL64td)

3- You're going to see information about your device. Click on Serial Number and you will be able to see your UDID.  <br>

![](/files/-Lnt-kLUi0KAJugsESwU)

![](/files/-Lnt-nUMMLW1N5JFjflr)

4- Right click on the UDID value and copy it!

Then, go to [Apple Developer website](https://developer.apple.com/) > Certificates, Identifiers & Profiles > Devices and add your new device pasting the UDID you've just copied.&#x20;

![](/files/-Lns_pcP29s-LsTItB6n)

Back to the Certificates, Identifiers & Profiles, click on Profiles. Then, click on the Development Provioning file you've created to test your application and Edit it.

![](/files/-LnsaLlPcLytFAM8H4TI)

You're going to see a list of already registred devices. Check the ones you want to use for testing your application, then click on `save` button and download the new version of your Development mobile provision.

{% hint style="success" %}
Now, you're ready for testing your TotalCross applications using your development certificate.
{% endhint %}


# Understanding TotalCross for Linux ARM

TotalCross now supports embedded systems!

## Introduction

See at this guide:

* Discover plugin for VS Code;
* Getting your Hello World App cooler;
* How to deploy;&#x20;
* After basics;

## Requirements

Complete the Getting Started:

{% content-ref url="/pages/-M2j3gfmD-ARGTuW\_2DN" %}
[Getting Started](/master/documentation/get-started)
{% endcontent-ref %}

The following electronic components are also required:

* Raspberry Pi 3;
* 7x jumpers male-female;
* Protoboard;
* LED RGB module (or common 4 pins LED RGB);
* Push-button module (or common push-button).

In order to execute Gpiod methods at your embedded device, you will also need to have the libgpiod-dev package installed in your board. You can do that by entering the following command at the device's terminal:

```java
$ sudo apt-get install libgpiod-dev
```

## **Guide**

### Discover VS Code plugin

A quick way to start using TotalCross is installing the [TotalCross extension for VS Code](https://marketplace.visualstudio.com/items?itemName=Italo.totalcross).&#x20;

**Step 1:** open VS Code console  (CTRL + Shift + P) and type TotalC… autocomplete should help!

![](/files/-Lun83v5b4ERDVyE7VT-)

**Step 2:** select *TotalCross: Create new Project;*&#x20;

**Step 3:** create a folder called *HelloWorld* and select it;&#x20;

**Step 4:** *GroupId* will be `com.totalcross`;

**Step 5:** *ArtifactId* will be `HelloWorld`*;*

**Step 6:** select the latest version of TotalCross SDK and `-linux-arm` platform;

![Click to expand](/files/-Lun8cZb1egyD-mqZBhj)

**Step 7:** open`RunHelloWorldApplication.java` and click *Run* (IDE). The result should be:

![Click  to expand](/files/-Lun9-JBKRLqV_24--Q4)

**Step 8:** watch the integrated simulator!

### Getting your Hello World App even more Cooler :cold\_face: :sweat\_smile:&#x20;

The following project deals with the control of an RGB LED with user interface buttons and a pin reset button!

![](/files/-LzgpT8LCC3-7z58c_wO)

**Step 1:** follow the schematic:

![](/files/-Lzcj5bEWsjwrkCoCK58)

**Step 2:** to work with pin logic after `public class HelloWorld extends MainWindow {` add:

```java
// Integers to store pin numbers
private int    R = 4, G = 17, B = 27, pushButton = 18;
// Integers to store state of each LED pin, 0 (LOW) and 1 (HIGH)
private int    sttR, sttG, sttB;
// Buttons to control colors 
private Button btnR, btnG, btnB;
```

{% hint style="danger" %}
If you need to work with different pinouts check the manufacturer manual!
{% endhint %}

**Step 3:** at  *HelloWorld.java* in `initUI()` code add:

```java
// Label helloWorld made on project creation
Label helloWorld = new Label("Hello World!");
// Change the position of label on the Y axis, with TOP (beginning of Y) + a fill of 20
add(helloWorld, CENTER, TOP + 20);
```

**Step 4:** then, board setup:

```java
// Board Setup
GpiodChip gpioChip = GpiodChip.open(0);
GpiodLine pinR = gpioChip.line(R);
GpiodLine pinG = gpioChip.line(G);
GpiodLine pinB = gpioChip.line(B);
GpiodLine pinPushButton = gpioChip.line(pushButton);
```

**Step 5:** pins setup:

```java
// Set LED pins as outputs and default value sttX
pinR.requestOutput("CONSUMER",sttR);
pinG.requestOutput("CONSUMER",sttG);
pinB.requestOutput("CONSUMER",sttB);
// Set Reset pin as input
pinPushButton.requestInput("CONSUMER");
```

**Step 6:** the red button:

```java
// The TotalCross button:
btnR = new Button("R");                                       // Button instantiation
                                                              // without text
btnR.setBackColor(Color.RED);                                 // Set background color (red)
btnR.addPressListener(new PressListener() {                   // Press event listener
    @Override
    public void controlPressed(ControlEvent controlEvent) {
        sttR = 1 - sttR;                                      // Invert pin state 
        pinR.setValue(sttR);                                  // Set value (HIGH or LOW)
    }
});
add(btnR, CENTER - 70, AFTER + 40);                           // To make horizontally aligned 
                                                              // buttons in the 'RGB' sequence,
                                                              // take the center reference and 
                                                              // decrease 70 to place the 
                                                              // leftmost R. In the Y axis just
                                                              // take the reference of the
                                                              // previous component and add 40
```

**Step 7:** and the other buttons:&#x20;

```java
btnG = new Button("G");
btnG.setBackColor(Color.GREEN);
btnG.addPressListener(new PressListener() {
    @Override
    public void controlPressed(ControlEvent controlEvent) {
        sttG = 1 - sttG;                                      // Pay attention to change pin!!!
        pinG.setValue(sttG);
    }
});
add(btnG, CENTER, SAME);                                      // The green button will be 
                                                              // placed at the center and in 
                                                              // the same line of previous 
                                                              // button

btnB = new Button("B");
btnB.setBackColor(Color.BLUE);
btnB.addPressListener(new PressListener() {
    @Override
    public void controlPressed(ControlEvent controlEvent) {
        sttB = 1 - sttB;                                       // Pay attention to change pin!!!
        pinB.setValue(sttB);      
    }
});
add(btnB, CENTER + 70, SAME);                                  // The last button will be placed 
                                                               // to the right of the center.
```

**Step 8:** finally we use a thread to check the state of the reset button:

```java
// A thread will be used to check every 20 ms, if the reset button has been pressed: if yes then 
// the pin state goes to LOW
new Thread() {
    @Override
    public void run() {
        while(true){
            if(pinPushButton.getValue() == 1) {
                sttG = 1 - sttG;
                sttR = 1 - sttR;
                sttB = 1 - sttB;
                pinR.setValue(sttR);
                pinG.setValue(sttG);
                pinB.setValue(sttB);
            }
            Vm.sleep(100);
        } 
    }
}.start();
```

**Step 9:** run *RunHelloWorldApplication.java* again and watch the results!&#x20;

![](/files/-LunDOEt3v1aVNDLqxjG)

{% hint style="info" %}
View fully code [here](https://gist.github.com/acmlira/e6c18f0a82688f750c1648af4d101344)&#x20;
{% endhint %}

### How to deploy

**Step 1:** open VS Code console  (CTRL + Shift + P) and select *TotalCross: Deploy*

![](/files/-LunDi6Z-vuOMZiz2XLo)

**Step 2:** a second dialog box will appear and just fill in the board's information:

![](/files/-LunDoXYlF_oU9Y39NP7)

**Step 3:** see the results in screen or VNC

![](/files/-LunDsKM3Yzmhnvpb_Ub)

### After basics

This was the beginning of application development for TotalCross embedded systems, how about taking a look at [TCSample](https://github.com/TotalCross/TCSample) and seeing all that can be done? See dashboard made especially for Web Summit 2019:

![](/files/-LunFODqxapPPckKLGiW)

## See more

Are you interested in development with embedded systems? Contact us via [Telegram](https://t.me/comunidadetotalcross)!&#x20;

![Bruno Muniz, Lucas Galvanini e Pedro Lyra no WebSummit](/files/-LunDx-hDEZniSPFP55o)

## References

* [Fritzing ](https://fritzing.org/home/)


# Running C++ applications with TotalCross

## Introduction

We hope you learn how to use TotalCross Runtime and Process implementations. See more about:

* Java 7 [Runtime class](https://docs.oracle.com/javase/7/docs/api/java/lang/Runtime.html)
* Java 8 [Process class](https://docs.oracle.com/javase/8/docs/api/java/lang/Process.html)

{% hint style="warning" %}
These implementations work only for Linux platforms
{% endhint %}

## Requirements

Can compile C ++ applications and finish Get Started:

{% content-ref url="/pages/-M618xtwOXMknrb8c83s" %}
[Running C++ applications with TotalCross](/master/documentation/guides/running-c++-applications-with-totalcross)
{% endcontent-ref %}

## Guide

Use external codes with Totalcross:

**Step 1:** create a blank project based in `HelloWorld` of VS Code plugin (we named it `RunningCpp`)

**Step 2:**  create an I/O sample in C++, in our case we did:

```cpp
#include <iostream>
#include <string>

int main()
{
    std::string input;
    std::getline(std::cin, input);
    std::cout << "\nI received: " + input + "\n";
    return 0;
}
```

{% hint style="info" %}
It's a simple application to get an I/O input and shortly thereafter return it as output.
{% endhint %}

**Step 3:** compile (something like this):

![](/files/-M65L0N0679y6r-Nxakg)

**Step 4:** inside `initUI` method at `RunningCpp` class, create a label to show the results:

```java
// Label to show the results
Label label;
label = new Label();
label.setBackForeColors(Color.WHITE,  Color.BLACK);
```

**Step 5:** create a child process:

```java
// Process initialization
Process process = null;
```

**Step 6:** output to the target program:

```java
// Output to program
byte[] output = "Take the output!!!\n".getBytes();              // convert string to
                                                                // byte array 
try {
    process = Runtime.getRuntime().exec("./io");                // execute your
                                                                // application (sh like)
    process.getOutputStream().write(output, 0, output.length);  // write output into 
                                                                // output strem
    process.waitFor();                                          // blocking method 
                                                                // (wait io finish)
} catch (IOException ioe) {
    ioe.printStackTrace();
} catch (InterruptedException ie) {
    ie.printStackTrace();
};
```

**Step 7:** read the C++ program output as input to TotalCross application

```java
// Input from program
String input;
try {
    // Read line by line the buffered stream
    LineReader lineReader = new LineReader(Stream.asStream(process.getInputStream()));
    while ((input = lineReader.readLine()) != null) {
        label.setText(input);
    }
} catch (IOException ioe) {
    ioe.printStackTrace();
};

// Add label to window
add(label, CENTER, CENTER);
```

**Step 8:** run `TotalCross: Package` with VS Code plugin or run `mvn package` in your terminal.

**Step 9:** copy C++ binary to target folder (something like):

![](/files/-M65qWMrKvOW9evE94lC)

**Step 10:** run your program!!!

## See more

See our article about how to run RS232 protocol. See the full code:

```java
package com.totalcross;

import java.io.IOException; 
import java.lang.Process;

import totalcross.ui.Label; 
import totalcross.ui.MainWindow; 
import totalcross.ui.gfx.Color; 

import totalcross.io.LineReader; 
import totalcross.io.Stream; 

import totalcross.sys.Settings;

public class RunningCPP extends MainWindow {
    public RunningCPP() {
        setUIStyle(Settings.MATERIAL_UI);
    }
    
    @Override
    public void initUI() {
        // Label to show the results
        Label label;
        label = new Label();
        label.setBackForeColors(Color.WHITE,  Color.BLACK);
    
        // Process initialization
        Process process = null;
    
        // Output to program
        byte[] output = "Take the output!!!\n".getBytes();              // convert string to
                                                                        // byte array 
        try {
            process = Runtime.getRuntime().exec("./io");                // execute your
                                                                        // application (sh like)
            process.getOutputStream().write(output, 0, output.length);  // write output into 
                                                                        // output strem
            process.waitFor();                                          // blocking method 
                                                                        // (wait io finish)
        } catch (IOException ioe) {
            ioe.printStackTrace();
        } catch (InterruptedException ie) {
            ie.printStackTrace();
        };
    
        // Input from program
        String input;
        try {
            LineReader lineReader = new LineReader(Stream.asStream(process.getInputStream()));
            while ((input = lineReader.readLine()) != null) {
                label.setText(input);
            }
        } catch (IOException ioe) {
            ioe.printStackTrace();
        };
    
        // Add label to window
        add(label, CENTER, CENTER);
    }
}
```

## References

* Java 7 [Runtime class](https://docs.oracle.com/javase/7/docs/api/java/lang/Runtime.html)
* Java 8 [Process class](https://docs.oracle.com/javase/8/docs/api/java/lang/Process.html)


# Web Services

![](/files/-Ld4K73dPtIe_tywrJlJ)

## Overview

In the previous session we explained how to store data locally and now we will learn how to get these local database and send information to an external or receive external database data through a solution used in systems integration and in communication between different applications, call Web Services.&#x20;

Through this technology, it is possible that applications that are under development will communicate with applications that have already been developed. In addition to enabling integration between different platforms developed in different programming languages.&#x20;

For businesses, Web Services can bring agility to processes and efficiency in communicating between production chains.&#x20;

## What are the benefits of Web Services?

Make use of Web Services behind both technical development and your business, such as:

1. Integration of information and systems;
2. Reuse code;
3. Reduction of development time;
4. Greater security;
5. Reduced costs.

## If they are different languages, how is communication between them?&#x20;

In order to communicate between two technologies constructed with different languages, a third language is required to function as "universal" and to guarantee communication. There are 3 protocols that play this role:&#x20;

* SOAP (Simple Object Access Protocol)

{% content-ref url="/pages/-Lh6LfqD\_mKqKQMv5jui" %}
[SOAP](/master/documentation/apis/soap)
{% endcontent-ref %}

* Socket&#x20;

{% content-ref url="/pages/-Lh6Js-z7tJtQ3d4rva8" %}
[Socket](/master/documentation/apis/socket)
{% endcontent-ref %}

* REST (Representational State Transfer).

The easiest and most recommended is the Rest, due to the ease to execute it and so is the one that we will demonstrate in the chapter below:

{% content-ref url="/pages/-Ld43xQBGKAYmbdssA8D" %}
[API Rest](/master/documentation/apis/api-rest)
{% endcontent-ref %}

## References

* [Open Soft - Web Service](https://www.opensoft.pt/web-service/)


# Miscelaneous

Here you find miscellaneous information on how to install dependencies, ...


# Java JDK 8

Java SE Development Kit 8 (JDK )

## Introduction

This guide will show you how to install **Java JDK 8** on **Windows**, **Mac OS X** and **Linux**.

{% hint style="success" %}
The choice of Java as a language for development was not occasional, but due to the fact that of the **21 million existing developers** in the world, **9 million are Java developers**, according to the Global Developers Population and Demographic Study in 2016. \
**It is one of the largest development communities in the world!**
{% endhint %}

## Guide

{% tabs %}
{% tab title="Windows" %}
**Step 1:** go to [**link**](https://www.oracle.com/java/technologies/javase/javase8u211-later-archive-downloads.html). Accept license agreement and download latest Java 8 JDK (32 or 64 bit) for Windows:

![](/files/-M26LMj3uOlUYyn8xsvJ)

{% hint style="info" %}
Requires an Oracle account
{% endhint %}

**Step 2:** if download is complete, run .exe for install. Click *Next*:

![](/files/-LyUSqdcBxHfx-lQeiPf)

**Step 3:** select the path of JDK installation and click *Next* :

![](/files/-LyUT9o_rkvYc85_1n4y)

**Step 4:** select the path of JRE installation and click *Next* :

![](/files/-LyUT_1xwh0w144c83Uz)

**Step 5:** once installation is complete click *Close* :

![](/files/-LyUTxImOIkGo0_WI1SP)

**Step 6:** open CMD (command line prompt) as administrator;

**Step 7:** set *JAVA\_HOME* environment variable:

`C:\> setx JAVA_HOME "C:\Program Files\Java\jdk1.8.0_231"`

**Step 8:** add  *JAVA\_HOME* and subfolders to *PATH* :

`C:\> setx PATH "%JAVA_HOME%;%JAVA_HOME%\bin;%JAVA_HOME%\lib;%PATH%;"`

**Step 9:** reopen  your CMD (command line prompt) and try:

`C:\> echo %JAVA_HOME%`

if response is `C:\Program Files\Java\jdk1.8.0_231` you installed everything correctly.
{% endtab %}

{% tab title="macOS X" %}
For the matter of simplicity you've chosen Java JDK 8 implementation of [AdoptOpenJDK](https://adoptopenjdk.net/).

Install brew, it is pretty easy and straightforward. Paste the following command on your terminal.

```
/usr/bin/ruby -e "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/master/install)"
```

Brew is a package manager that easily allows you to install packages on macOS X, it is similar to the debian package manager apt-get. Paste the command bellow on you terminal and you will have the Java JDK 8 on your machine.

```
brew cask install adoptopenjdk/openjdk/adoptopenjdk8
```

{% endtab %}

{% tab title="Linux (debian based)" %}
**Step 1:** open terminal (CTRL+ALT+T);

**Step 2:** updates APT:

`$ sudo apt update`&#x20;

**Step 3:** install Java 8:

`$ sudo apt-get install openjdk-8-jdk`

**(Optional):** if you already have another Java version:

`$ sudo update-alternatives --config java`

and select the correct version.
{% endtab %}
{% endtabs %}

{% hint style="success" %}
You have successfully installed Java JDK 8 on your machine.
{% endhint %}

## See more

After that it's possible to [start](https://totalcross.gitbook.io/playbook/learn-totalcross/getting-started/) into many IDEs! Start with Visual Studio Code or another non Maven friendly, following the [Maven installation guide](https://totalcross.gitbook.io/playbook/learn-totalcross/basic-requirements/maven/).


# Maven

Apache Maven 3.6.X

## Introduction

TotalCross uses Maven to automate compilation, being quick and easy to use.

> *"Apache Maven is a software project management and comprehension tool. Based on the concept of a project object model (POM), Maven can manage a project's build, reporting and documentation from a central piece of information."*

This article targets users of Visual Studio Code and other IDEs that do not have Maven integration.

## Guide

{% tabs %}
{% tab title="Windows" %}
Next steps requires *administrator* privileges.

**Step 1:** go to [**link**](http://maven.apache.org/download.cgi). Download the latest Maven .zip:

![](/files/-M26QmBJGquIwaeReROy)

**Step 2:** unzip into *C:/Program Files/Maven/* (recommended);

**Step 3:** open CMD (command line prompt) as administrator;

**Step 4:** set *MAVEN\_HOME* environment variable:

`C:\> setx MAVEN_HOME "C:\Program Files\Maven\apache-maven-3.6.3"`

**Step 5:** add *MAVEN\_HOME* and bin subfolder to PATH :

`C:\> setx PATH "%MAVEN_HOME%;%MAVEN_HOME%\bin;%PATH%;"`

**Step 6:** reopen  your CMD (command line prompt) and try:

`C:\> mvn -version`

if response is `Apache Maven 3.6.3` you installed everything correctly.
{% endtab %}

{% tab title="macOS X" %}
Install brew, it is pretty easy and straightforward. Paste the following command on your terminal.

```
/usr/bin/ruby -e "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/master/install)"
```

Brew is a package manager that easily allows you to install packages on macOS X, it is similar to the debian package manager apt-get. Paste the command bellow on you terminal and you will have the Java JDK 8 on your machine.

```
brew install maven 
```

{% endtab %}

{% tab title="Linux (Debian based)" %}
Next steps requires *sudo* privileges.

**Step 1:** open terminal (CTRL+ALT+T);

**Step 2:** update APT:

`$ sudo apt-get update`

**Step 3:** install Maven:

`$ sudo apt-get -y install maven`

**Step  4:** check installation:

`$ mvn -version`

{% hint style="info" %}
TotalCross needs Maven 3.6.X or later
{% endhint %}
{% endtab %}
{% endtabs %}

## See more

With these requirements, it's possible to [start](https://totalcross.gitbook.io/playbook/learn-totalcross/getting-started) with TotalCross!


# Installing Visual Studio Code

How to install Visual Studio Code on your operational system.

{% tabs %}
{% tab title="Linux" %}
The easiest way to install is by opening the .deb package via Software Center GUI. If your Linux distribution is Debian based (Debian/Ubuntu) [download your Visual Studio Code .deb Package](https://code.visualstudio.com/Download) and install it.&#x20;

If you prefer to install using your terminal, type the command`sudo apt-get install code`

![](/files/-M29NH4hDzoj0SUkFhEq)

For more information access <https://code.visualstudio.com/docs/setup/linux>
{% endtab %}

{% tab title="Windows" %}
[Download the Visual Studio Code installer](https://code.visualstudio.com/Download) and run the installer. If you download a Zip archive, extract it and run Code from there.&#x20;

For more information access <https://code.visualstudio.com/docs/setup/windows>
{% endtab %}

{% tab title="Mac OS X" %}
[Download Visual Studio Code installer](https://code.visualstudio.com/Download) and double-click on the downloaded file to open its contents. Drag Visual Studio Code.app to the Applications folder. To make it available in the Launchpad and to add Visual Studio Code to your Dock,  right-click the icon and choose Options >> Keep in Doc.

{% hint style="info" %}
You can also use [brew](https://brew.sh/) to install it by typing the following command:&#x20;

```
brew cask install visual-studio-code
```

{% endhint %}

For more information access <https://code.visualstudio.com/docs/setup/mac>
{% endtab %}
{% endtabs %}


# FAQ

## How to solve "Could not find the file jarsigner.exe. Make sure you have installed a JDK than has this file in the bin folder" error?

this error normally occurs in two situations:

1. A **%JavaHome% environment variable** is using JRE instead of JDK. In this case you can see how to configure by **clicking** [**here**](https://www.ntu.edu.sg/home/ehchua/programming/howto/environment_variables.html).
2. Eclipse itself is pointing erroneously at the JRE. In this case, just go to the top bar in **Windows > Preferences**.  Then it will open a window and you click on **Java > Installed JREs > add**.  Another window will appear, just click "**Next**" and then click "**Directory**" and **select the JDK folder that is inside the java folder**, where you installed it (usually C: \Program Files\Java).  Finally, just click select **folder> finish**. **Confirm that JDK is selected** and then just click "**Apply and Close**" and then **restart** eclipse.&#x20;

See step-by-step from item 2 below:

![1. Windows \&gt; Preferences](/files/-Ltf9hwnXKxiYLzkdlzU)

![2. click on Java \&gt; Installed JREs \&gt; add. ](/files/-Ltf9p6V5h7cAQM1_sDC)

![3. just click "Next"](/files/-Ltf9xbX_y_Quw9H1eC7)

![4. click "Directory" and select the JDK folder](/files/-LtfALR8MZDNeQ69V1dH)

![5. Just click Finish ](/files/-LtfAUM5bMlHPcFO7tRy)

![6. Confirm that JDK is selected and then just click "Apply and Close"](/files/-LtfAmzUg3xmYpkAdc7b)

## How to develop for RPI using TotalCross?

Just add in pom.xml instead of the totalcross SDK version, the following command:

```markup
<scope>system</scope>
<systemPath>caminho\TotalCross\dist\tc.jar</systemPath>
```

That done, you can deploy it. Already to develop, is the same way that develops for mobile.

## We have a proxy and it is blocking the compilation of our app what do you suggest?

Just add iso to pom.xml:

```markup
<dependency>
  <groupId>com.totalcross</groupId>
  <artifactId>totalcross-sdk</artifactId>
  <version>5.1.1</version>
  <scope>system</scope>
  <systemPath> PATH__TO__YOUR__TOTALCROSS__JAR__FILE </systemPath>
</dependency>

<dependency>
   <groupId>org.xerial</groupId>
   <artifactId>sqlite-jdbc</artifactId>
   <version>3.8.7</version>
   <scope>compile</scope>
</dependency>
```

{% hint style="warning" %}
Attention: Please be aware if the version indicated on the pom is the same as your machine.
{% endhint %}

## How to disable backup / restore in TotalCross?

To disable backup just add `Settings.allowBackup = true` within the constructor method in your application's MainWindow

## Every time there is a touch on the screen, the event is triggered. How to fix?

This may be happening because you are using the `pendown` instead of the `penup`. To better understand, follow the definitions:

* **`pendown` is triggered when there is a touch on the screen.**
* **`penup` is triggered when finger flips the screen** (or mouse/key, depending on the platform).

To find out if there was a click, it can be detected through the **`pendrag`**, and if it is positive, do not trigger the `penup`.

Another smarter solution is to use the **`this.hadParentScrolled()`** method within your pendown method, to **identify whether the action is being triggered during the scrolling of some parent component**. As shown below:

```java
if (!this.hadParentScrolled()) {
    // código de pen down
}
```

## How to navigate between screens (Containers and Windows)?

In the case of **Containers**:

* `swap(new InitialScreen());` - If you are in the Main Window and want to call a Container, simply use the `swap()` command.
* `MainWindow.getMainWindow().Swap(new SecondScreen());` - If you are in a container or Window and want to call a Container just use the command.

In the case of **Windows**:

* `.popup()` - The execution **stops** after the `popup()`command is executed.
* `.popupNonBlocking()` - the execution **continues** right after the popup command, even with the window still open

To understand more in depth how best to use and other ways to navigate between user interfaces, click [here](https://totalcross.gitbook.io/playbook/guideline/container-x-window)

## Is it possible for the buttons to be round?

Yes, if it is an FAB we have a component of its own, the `FloatingButton`. In other cases, you can change using NinePatch or do the most recommended: use an ImageButton as in the following example:

```java
Image original = Images.getTotalCrossLogo();
// If you need to resize it, this is the method call.
Image aumentada;
try {
    aumentada = original.hwScaledBy(0.5, 0.5);
    Button btn = new Button(aumentada);
    // If you want to change the image when the button is clicked, use this property
    // The "getTouchedUpInstance" method is a good place-holder.    btn.pressedImage = aumentada.getTouchedUpInstance((byte) 64, (byte) 0);
    // Finally, take a default button border and ninepatch
    btn.setBorder(Button.BORDER_NONE);
    btn.setNinePatch(null);

    add(btn, CENTER, CENTER);
} catch (ImageException e) {
    e.printStackTrace();
}
```

## Slowdown when opening in Windows with a Roboto font

Just use `Font.getFont ("Roboto Medium", true, FontSize);`

## Is there a maximum file size to be retrieved by the Vm.getFile (String) method?7

I checked it here, Vm.getFile looks for the file in the TCZs. An embedded file in TCZ has its size given in an int32 `uncompressedSize`; therefore, it can not be more than 4gb. As TotalCross apps are 32bits, as far as I can remember, I would still lower this limit to 2gb, because the system will not be able to allocate more than this contiguous memory.

## What is the difference between Window and Container?

First, the main function of each is different:

* **Container**: A control capable of containing other controls. It is primarily a form of organization.
* **Window**: it is a control capable of overlapping others, creating an illusion of depth. In addition, Windows is also containers, as they can accommodate several components within them.

To better understand the difference between them in specific cases and how to use both in the most appropriate way, access the [Windows X Container session](https://learn.totalcross.com/guideline/container-x-window).

## Is it possible to search for GPS position through Triangulation?

By default the **GPS class** performs location **only via GPS**, but on Android, you can change your behavior to use Google Play Services to get the location. To do this, change the **field precision** value to to **`LOW_GPS_PRECISION`**.

Location by Google Play Services is based on a *variety of information*, including **Wifi and Bluetooth**. If you specifically want information about the network location used, you can use the CellInfo class in WinCE or Android.

## How to use the DecimalFormat on TotalCross?

Totalcross doesn't have the `java.text` so the DecimalFormat is not on our SDK.

## How to ativate the OK (ENTER) button on Android

Just use the .addKeyListener and add an action in the specialkeyPressed method like no example below:

```java
Edit edtExit = new Edit();
    edtExit.addKeyListener(new KeyListener() {
        ...
        @Override
        public void specialkeyPressed(KeyEvent keyEvent) {
            if(keyEvent.isActionKey()){
                proximaTela();
            }
        }
    });
add(edtExit, CENTER, AFTER  + 40, PARENTSIZE, PREFERRED);
```




---

[Next Page](/llms-full.txt/1)

