Package: carta
CartaPython library for making GUI applications on the reMarkable tablet wrapped around the"simple"applicationSimulating the ReMarkable deviceIt can be a pain having to transfer the script & run the script from the RM each time. Especially if you want to use the device for something else at the time. To help with this, I've made the option to manually set the command to asimplex64 binary that can be run on linux which will write tofb.pnm- This is the framebuffer file that you'll need to read from.In themiscfolder I've provided the binary and a basic script as an example. To use this, just initialize the ReMarkable object like so:rm=ReMarkable(simple="path/to/simple/binay")Finally, checkoutremarkable-simfor events (like button clicking) supportUsing CartaCarta's purpose is to function as a Python wrapper aroundsas- the simple app script for making apps on the reMarkable without need to compiling code.
It's written in python and is designed to be as user-friendly and easy to use as possible.To use it, you'll need to install a few things onto your reMarkable, in an SSH session:toltec- an unofficial reMarkable-specific package manager
See instructions on toltec's website.simpleopkg install simplerM2 users needdisplayopkg install displaypip- the package manager for pythonwget https://bootstrap.pypa.io/get-pip.py
python get-pip.pycarta- this librarypip install cartaAfter having installed all the prerequisites, you are ready to start developing.
Make a python script on the rM and runchmod +xon the script to make it executable.
You'll also need to add ashebangto the script (#!/opt/bin/pythonat the top) so that it knows what to run it with.Here's an example script that you can copy:#!/opt/bin/pythonfromcartaimportReMarkable,Widgetrm=ReMarkable()my_button=Widget(id="but1",typ="button",value="Hello!",x="50%",y="50%")rm.add(my_button)rm.display()Let's walk through it line by line,fromcartaimportReMarkable,Widgetrm=ReMarkable()This imports the necessary "parts" for the library to function. TheReMarkableclass is the main "driver" code and handles everything from interacting withsimpleto display your app to managing the widgets themselves. Thewidgetdataclass are the actual contents themselves and there are 6core types;LabelParagraphButtonTextInputText AreaImagePlease refer tothesimplespecfor more detailed information.my_button=Widget(id="but1",typ="button",value="Hello!",x="50%",y="50%")Here we are making a newWidgetwhich we have assigned tomy_button.
The following is a table outlining information about supported arguments which can be given.ArgumentRequiredUseSupported inputsNotesidYesUsed to uniquely identify a widget when being interacted withAny string that hasn't been used beforeSpaces will be converted to_typYesGives a widget specific properties so it knows what to be used asAny from the following:label,paragraph,burtton,textinput,textarea,imageRange is a WIPvalueYesWhat will be displayed on the widgetAny string (Image path for theimagewidget type)Be careful about using new linesxYesUsed to calculate the rendering position of the widgetA percentage, keyword or an integerSupported keywords aresame(same value as previous item) andstep(previous item's cord + previous items size)yYesUsed to calculate the rendering position of the widgetA percentage, keyword or an integerSupported keywords aresame(same value as previous item) andstep(previous item's cord + previous items size)widthNo (Automatically calculated)The width of the widgetAny integerYou might have some trouble with getting the right value for thisheightNo (Automatically calculated)The height of the widgetAny integerYou might have some trouble with getting the right value for thisjustifyNo (Optional for buttons)Where the text sits in a buttonAny string from the following:center,right,leftFinally, we want to add the widget to the actual screen.rm.add(my_button)rm.display()I've made the decision to have widgets be manually added like this to make it easier to manage when making apps).
We can do this easily withadd(args*), whereargs*are anyWidgettypes - For example,rm.add(my_button,label1,logo)And then display it to the rM! Thedisplay()function will take all the currently activeWidgetsand convert them into something that simple can understand and render. The active widgets are all stored in thescreenlist (in this caserm.screen) and you can easily access and modify any of the widgets in there at any time via thelookupfunction which will return theWidgetobject that has the corresponding IDprint(rm.lookup("<id>"))To remove aWidgetyou can use theremove()function and either supply it anIDorWidgetobject like sorm.remove("<id>")rm.remove(my_button)In case you want to fully clear the screen, you can use theeclear()function - however this does require the modified updated simple binary whichokehcan provide for you!rm.eclear()Finally, there are two other options that theReMarkableclass has that we can modify.Fontsize - Changes the fontsize of the text on the screenTimeout - The time aftersimplequits if no input is givenIn this case, carrying on the program afterrm.display()has been run and no input has been given after a set timeFor example, if we wanted to make thefontsize24 and timeout the program after30seconds we would dorm.timeout=32rm.fontsize=24When you run thedisplayfunction, carta will wait on any input being givenORthe timeout being reached. When it's done this, it will return adictobject with the input given.clicked=rm.display()print(clicked)# {"<id>": True}If it's abuttonthat has been pressed it will returnTrueas the value, if anything else has been given it will use that specific input (for example, from the keyboard) as the value.Hope this guide was helpful, feel free to ask if you need some help (jake.shon discord)