Search
45 | 46 | 54 | 55 | 56 |57 | Searching for multiple words only shows matches that contain 58 | all words. 59 |
60 | 61 | 62 | 67 | 68 | 69 | 70 |├── docs ├── .nojekyll ├── .gitignore ├── _static │ ├── custom.css │ ├── file.png │ ├── minus.png │ ├── plus.png │ ├── documentation_options.js │ ├── _sphinx_javascript_frameworks_compat.js │ ├── nature.css │ ├── pygments.css │ ├── language_data.js │ ├── doctools.js │ └── alabaster.css ├── objects.inv ├── _sources │ ├── termuxgui.oo.rst.txt │ ├── termuxgui.rst.txt │ └── index.rst.txt ├── .buildinfo ├── search.html ├── py-modindex.html ├── index.html └── searchindex.js ├── pyproject.toml ├── gendoc.sh ├── docsource ├── termuxgui.oo.rst ├── termuxgui.rst ├── index.rst └── conf.py ├── tutorial ├── helloworld.py ├── helloimage.py ├── widget.py ├── webview.py ├── linearlayout1.py ├── linearlayout2.py ├── hellolayout.py ├── swiperefresh.py ├── inputs2.py ├── inputs.py ├── helloevents.py ├── pagedlist.py ├── pages.py ├── buffers.py └── notify.py ├── src └── termuxgui │ ├── viewgroup.py │ ├── oo │ ├── spinner.py │ ├── webview.py │ ├── imageview.py │ ├── progressbar.py │ ├── switch.py │ ├── space.py │ ├── checkbox.py │ ├── tablayout.py │ ├── togglebutton.py │ ├── radiobutton.py │ ├── viewgroup.py │ ├── button.py │ ├── framelayout.py │ ├── gridlayout.py │ ├── textview.py │ ├── linearlayout.py │ ├── swiperefreshlayout.py │ ├── radiogroup.py │ ├── horizontalscrollview.py │ ├── nestedscrollview.py │ ├── view.py │ ├── edittext.py │ ├── __init__.py │ ├── activity.py │ └── connection.py │ ├── space.py │ ├── framelayout.py │ ├── task.py │ ├── button.py │ ├── gridlayout.py │ ├── linearlayout.py │ ├── checkbox.py │ ├── togglebutton.py │ ├── switch.py │ ├── radiobutton.py │ ├── radiogroup.py │ ├── progressbar.py │ ├── spinner.py │ ├── swiperefreshlayout.py │ ├── compoundbutton.py │ ├── tablayout.py │ ├── edittext.py │ ├── horizontalscrollview.py │ ├── nestedscrollview.py │ ├── imageview.py │ ├── msg.py │ ├── buffer.py │ ├── __init__.py │ ├── event.py │ ├── textview.py │ ├── webview.py │ ├── activity.py │ ├── remoteviews.py │ ├── notification.py │ ├── view.py │ └── connection.py ├── setup.cfg ├── README.md ├── .github └── workflows │ └── python-publish.yml ├── tutorial_oop └── helloworld.py ├── TUTORIAL_OOP.md └── .gitignore /docs/.nojekyll: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /docs/.gitignore: -------------------------------------------------------------------------------- 1 | .doctrees -------------------------------------------------------------------------------- /docs/_static/custom.css: -------------------------------------------------------------------------------- 1 | /* This file intentionally left blank. */ 2 | -------------------------------------------------------------------------------- /docs/objects.inv: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tareksander/termux-gui-python-bindings/HEAD/docs/objects.inv -------------------------------------------------------------------------------- /docs/_static/file.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tareksander/termux-gui-python-bindings/HEAD/docs/_static/file.png -------------------------------------------------------------------------------- /docs/_static/minus.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tareksander/termux-gui-python-bindings/HEAD/docs/_static/minus.png -------------------------------------------------------------------------------- /docs/_static/plus.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tareksander/termux-gui-python-bindings/HEAD/docs/_static/plus.png -------------------------------------------------------------------------------- /pyproject.toml: -------------------------------------------------------------------------------- 1 | [build-system] 2 | requires = [ 3 | "setuptools>=42", 4 | "wheel" 5 | ] 6 | build-backend = "setuptools.build_meta" 7 | -------------------------------------------------------------------------------- /gendoc.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | cd "$(dirname "$0")" || { echo "cd failed"; exit 1; } 3 | # pypi package: sphinx 4 | sphinx-build -b html docsource/ docs/ 5 | -------------------------------------------------------------------------------- /docsource/termuxgui.oo.rst: -------------------------------------------------------------------------------- 1 | termuxgui.oo package 2 | ==================== 3 | 4 | 5 | Module contents 6 | --------------- 7 | 8 | .. automodule:: termuxgui.oo 9 | :members: 10 | :undoc-members: 11 | :show-inheritance: 12 | -------------------------------------------------------------------------------- /docs/_sources/termuxgui.oo.rst.txt: -------------------------------------------------------------------------------- 1 | termuxgui.oo package 2 | ==================== 3 | 4 | 5 | Module contents 6 | --------------- 7 | 8 | .. automodule:: termuxgui.oo 9 | :members: 10 | :undoc-members: 11 | :show-inheritance: 12 | -------------------------------------------------------------------------------- /docs/.buildinfo: -------------------------------------------------------------------------------- 1 | # Sphinx build info version 1 2 | # This file hashes the configuration used when building these files. When it is not found, a full rebuild will be done. 3 | config: 6d7e59f3f36002c5c4d12ec73f0caec0 4 | tags: 645f666f9bcd5a90fca523b33c5a78b7 5 | -------------------------------------------------------------------------------- /docsource/termuxgui.rst: -------------------------------------------------------------------------------- 1 | termuxgui package 2 | ================= 3 | 4 | Subpackages 5 | ----------- 6 | 7 | .. toctree:: 8 | :maxdepth: 4 9 | 10 | termuxgui.oo 11 | 12 | Module contents 13 | --------------- 14 | 15 | .. automodule:: termuxgui 16 | :members: 17 | :undoc-members: 18 | :show-inheritance: 19 | 20 | 21 | -------------------------------------------------------------------------------- /docs/_sources/termuxgui.rst.txt: -------------------------------------------------------------------------------- 1 | termuxgui package 2 | ================= 3 | 4 | Subpackages 5 | ----------- 6 | 7 | .. toctree:: 8 | :maxdepth: 4 9 | 10 | termuxgui.oo 11 | 12 | Module contents 13 | --------------- 14 | 15 | .. automodule:: termuxgui 16 | :members: 17 | :undoc-members: 18 | :show-inheritance: 19 | 20 | 21 | -------------------------------------------------------------------------------- /tutorial/helloworld.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | 3 | import termuxgui as tg 4 | import time 5 | 6 | with tg.Connection() as c: 7 | # create a new Activity. By default, a new Task as created. 8 | a = tg.Activity(c) 9 | # you can find the Task under a.t 10 | 11 | # create the TextView. 12 | tv = tg.TextView(a, "Hello world!") 13 | 14 | time.sleep(5) 15 | tv.settext("Goodbye world!") 16 | 17 | time.sleep(5) 18 | -------------------------------------------------------------------------------- /tutorial/helloimage.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | 3 | import termuxgui as tg 4 | import sys 5 | import time 6 | import io 7 | 8 | image = None 9 | with io.open(sys.argv[1], "rb") as f: 10 | image = f.read() 11 | 12 | with tg.Connection() as c: 13 | a = tg.Activity(c, pip=True) # start the activity in picture-in-picture mode 14 | 15 | iv = tg.ImageView(a) # create a ImageView to display the image 16 | 17 | # Set the image 18 | iv.setimage(image) 19 | 20 | time.sleep(5) 21 | -------------------------------------------------------------------------------- /docs/_static/documentation_options.js: -------------------------------------------------------------------------------- 1 | var DOCUMENTATION_OPTIONS = { 2 | URL_ROOT: document.getElementById("documentation_options").getAttribute('data-url_root'), 3 | VERSION: '0.1.5', 4 | LANGUAGE: 'en', 5 | COLLAPSE_INDEX: false, 6 | BUILDER: 'html', 7 | FILE_SUFFIX: '.html', 8 | LINK_SUFFIX: '.html', 9 | HAS_SOURCE: true, 10 | SOURCELINK_SUFFIX: '.txt', 11 | NAVIGATION_WITH_KEYS: false, 12 | SHOW_SEARCH_SUMMARY: true, 13 | ENABLE_SEARCH_SHORTCUTS: true, 14 | }; -------------------------------------------------------------------------------- /src/termuxgui/viewgroup.py: -------------------------------------------------------------------------------- 1 | from termuxgui.activity import Activity 2 | from termuxgui.view import View 3 | 4 | 5 | class ViewGroup(View): 6 | """This represents a generic ViewGroup.""" 7 | 8 | def __init__(self, activity: Activity, id: int): 9 | View.__init__(self, activity, id) 10 | 11 | def clearchildren(self): 12 | """Removes all child Views of this ViewGroup.""" 13 | self.a.c.send_msg({"method": "deleteChildren", "params": {"aid": self.a.aid, "id": self.id}}) 14 | -------------------------------------------------------------------------------- /src/termuxgui/oo/spinner.py: -------------------------------------------------------------------------------- 1 | from typing import Optional, Literal 2 | 3 | import termuxgui as tg 4 | from termuxgui.oo.view import View 5 | 6 | 7 | class Spinner(View, tg.Spinner): 8 | """This represents a Spinner.""" 9 | 10 | def __init__(self, activity: tg.Activity, parent: Optional[View] = None, 11 | visibility: Optional[Literal[0, 1, 2]] = None): 12 | tg.Spinner.__init__(self, activity, parent, visibility) 13 | View.__init__(self, activity, self.id, parent) 14 | 15 | -------------------------------------------------------------------------------- /src/termuxgui/oo/webview.py: -------------------------------------------------------------------------------- 1 | from typing import Optional, Literal 2 | 3 | import termuxgui as tg 4 | 5 | from termuxgui.oo.view import View 6 | 7 | 8 | class WebView(View, tg.WebView): 9 | """This represents a WebView.""" 10 | 11 | def __init__(self, activity: tg.Activity, parent: Optional[View] = None, 12 | visibility: Optional[Literal[0, 1, 2]] = None): 13 | tg.WebView.__init__(self, activity, parent, visibility) 14 | View.__init__(self, activity, self.id, parent) 15 | 16 | 17 | -------------------------------------------------------------------------------- /src/termuxgui/oo/imageview.py: -------------------------------------------------------------------------------- 1 | from typing import Optional, Literal 2 | 3 | import termuxgui as tg 4 | 5 | from termuxgui.oo.view import View 6 | 7 | 8 | class ImageView(View, tg.ImageView): 9 | """This represents an ImageView.""" 10 | 11 | def __init__(self, activity: tg.Activity, parent: Optional[View] = None, 12 | visibility: Optional[Literal[0, 1, 2]] = None): 13 | tg.ImageView.__init__(self, activity, parent, visibility) 14 | View.__init__(self, activity, self.id, parent) 15 | 16 | 17 | -------------------------------------------------------------------------------- /src/termuxgui/oo/progressbar.py: -------------------------------------------------------------------------------- 1 | from typing import Optional, Literal 2 | 3 | import termuxgui as tg 4 | 5 | from termuxgui.oo.view import View 6 | 7 | 8 | class ProgressBar(View, tg.ProgressBar): 9 | """This represents a ProgressBar.""" 10 | 11 | def __init__(self, activity: tg.Activity, parent: Optional[View] = None, 12 | visibility: Optional[Literal[0, 1, 2]] = None): 13 | tg.ProgressBar.__init__(self, activity, parent, visibility) 14 | View.__init__(self, activity, self.id, parent) 15 | 16 | -------------------------------------------------------------------------------- /tutorial/widget.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | 3 | import sys 4 | import termuxgui as tg 5 | import time 6 | import os 7 | 8 | with tg.Connection() as c: 9 | wid = sys.argv[1] 10 | # Create a remote layout 11 | rv = tg.RemoteViews(c) 12 | # Add a TextView 13 | tv = rv.addTextView() 14 | while True: 15 | files = os.listdir() 16 | files.sort() 17 | # Set the text 18 | rv.setText(tv, '\n'.join(files)) 19 | # update the widget 20 | rv.updateWidget(wid) 21 | time.sleep(1) 22 | -------------------------------------------------------------------------------- /src/termuxgui/oo/switch.py: -------------------------------------------------------------------------------- 1 | from typing import Optional, Literal 2 | 3 | import termuxgui as tg 4 | 5 | from termuxgui.oo.view import View 6 | 7 | 8 | class Switch(View, tg.Switch): 9 | """This represents a Switch.""" 10 | 11 | def __init__(self, activity: tg.Activity, text: str, parent: Optional[View] = None, checked: bool = False, 12 | visibility: Optional[Literal[0, 1, 2]] = None): 13 | tg.Switch.__init__(self, activity, text, parent, checked, visibility) 14 | View.__init__(self, activity, self.id, parent) 15 | -------------------------------------------------------------------------------- /src/termuxgui/oo/space.py: -------------------------------------------------------------------------------- 1 | from typing import Optional, Literal 2 | 3 | import termuxgui as tg 4 | 5 | from termuxgui.oo.view import View 6 | 7 | 8 | class Space(View, tg.Space): 9 | """This represents a Space. You can use this to create empty space in your layout.""" 10 | 11 | def __init__(self, activity: tg.Activity, parent: Optional[View] = None, 12 | visibility: Optional[Literal[0, 1, 2]] = None): 13 | tg.Space.__init__(self, activity, parent, visibility) 14 | View.__init__(self, activity, self.id, parent) 15 | -------------------------------------------------------------------------------- /src/termuxgui/oo/checkbox.py: -------------------------------------------------------------------------------- 1 | from typing import Optional, Literal 2 | 3 | import termuxgui as tg 4 | 5 | from termuxgui.oo.view import View 6 | 7 | 8 | class Checkbox(View, tg.Checkbox): 9 | """This represents a CheckBox.""" 10 | 11 | def __init__(self, activity: tg.Activity, text: str, parent: Optional[View] = None, checked: bool = False, 12 | visibility: Optional[Literal[0, 1, 2]] = None): 13 | tg.Checkbox.__init__(self, activity, text, parent, checked, visibility) 14 | View.__init__(self, activity, self.id, parent) 15 | -------------------------------------------------------------------------------- /src/termuxgui/oo/tablayout.py: -------------------------------------------------------------------------------- 1 | from typing import Optional, Literal 2 | 3 | import termuxgui as tg 4 | from termuxgui.oo.viewgroup import ViewGroup 5 | 6 | 7 | class TabLayout(ViewGroup, tg.TabLayout): 8 | """This represents a TabLayout.""" 9 | 10 | def __init__(self, activity: tg.Activity, parent: Optional[ViewGroup] = None, 11 | visibility: Optional[Literal[0, 1, 2]] = None): 12 | tg.TabLayout.__init__(self, activity, parent, visibility) 13 | ViewGroup.__init__(self, activity, self.id, parent) 14 | 15 | 16 | 17 | -------------------------------------------------------------------------------- /src/termuxgui/oo/togglebutton.py: -------------------------------------------------------------------------------- 1 | from typing import Optional, Literal 2 | 3 | import termuxgui as tg 4 | 5 | from termuxgui.oo.view import View 6 | 7 | 8 | class ToggleButton(View, tg.ToggleButton): 9 | """This represents a ToggleButton.""" 10 | 11 | def __init__(self, activity: tg.Activity, parent: Optional[View] = None, checked: bool = False, 12 | visibility: Optional[Literal[0, 1, 2]] = None): 13 | tg.ToggleButton.__init__(self, activity, parent, checked, visibility) 14 | View.__init__(self, activity, self.id, parent) 15 | -------------------------------------------------------------------------------- /docsource/index.rst: -------------------------------------------------------------------------------- 1 | .. termuxgui documentation master file, created by 2 | sphinx-quickstart on Tue Sep 20 01:21:45 2022. 3 | You can adapt this file completely to your liking, but it should at least 4 | contain the root `toctree` directive. 5 | 6 | termuxgui Python Documentation 7 | ===================================== 8 | 9 | .. toctree:: 10 | :maxdepth: 4 11 | :caption: Contents: 12 | 13 | termuxgui 14 | 15 | 16 | 17 | 18 | Indices and tables 19 | ================== 20 | 21 | * :ref:`genindex` 22 | * :ref:`modindex` 23 | * :ref:`search` 24 | -------------------------------------------------------------------------------- /docs/_sources/index.rst.txt: -------------------------------------------------------------------------------- 1 | .. termuxgui documentation master file, created by 2 | sphinx-quickstart on Tue Sep 20 01:21:45 2022. 3 | You can adapt this file completely to your liking, but it should at least 4 | contain the root `toctree` directive. 5 | 6 | termuxgui Python Documentation 7 | ===================================== 8 | 9 | .. toctree:: 10 | :maxdepth: 4 11 | :caption: Contents: 12 | 13 | termuxgui 14 | 15 | 16 | 17 | 18 | Indices and tables 19 | ================== 20 | 21 | * :ref:`genindex` 22 | * :ref:`modindex` 23 | * :ref:`search` 24 | -------------------------------------------------------------------------------- /src/termuxgui/oo/radiobutton.py: -------------------------------------------------------------------------------- 1 | from typing import Optional, Literal 2 | 3 | import termuxgui as tg 4 | 5 | from termuxgui.oo.view import View 6 | 7 | 8 | class RadioButton(View, tg.RadioButton): 9 | """This represents a RadioButton.""" 10 | 11 | def __init__(self, activity: tg.Activity, text: str, parent: Optional[View] = None, checked: bool = False, 12 | visibility: Optional[Literal[0, 1, 2]] = None): 13 | tg.RadioButton.__init__(self, activity, text, parent, checked, visibility) 14 | View.__init__(self, activity, self.id, parent) 15 | -------------------------------------------------------------------------------- /src/termuxgui/oo/viewgroup.py: -------------------------------------------------------------------------------- 1 | from typing import Optional 2 | 3 | import termuxgui as tg 4 | 5 | from abc import ABC 6 | from termuxgui.oo.view import View 7 | 8 | 9 | class ViewGroup(View, tg.ViewGroup, ABC): 10 | 11 | def __init__(self, activity: tg.Activity, id: int, parent: Optional['ViewGroup']): 12 | View.__init__(self, activity, id, parent) 13 | self.views = [] 14 | 15 | def clearchildren(self): 16 | """Removes all child Views of this ViewGroup.""" 17 | tg.ViewGroup.clearchildren(self) 18 | self.views = [] 19 | -------------------------------------------------------------------------------- /src/termuxgui/oo/button.py: -------------------------------------------------------------------------------- 1 | from typing import Optional, Literal 2 | 3 | import termuxgui as tg 4 | 5 | from termuxgui.activity import Activity 6 | from termuxgui.oo.view import View 7 | 8 | 9 | class Button(View, tg.Button): 10 | """This represents a Button.""" 11 | 12 | def __init__(self, activity: Activity, text: str, parent: Optional[View] = None, allcaps: bool = False, 13 | visibility: Optional[Literal[0, 1, 2]] = None): 14 | tg.Button.__init__(self, activity, text, parent, allcaps, visibility) 15 | View.__init__(self, activity, self.id, parent) 16 | -------------------------------------------------------------------------------- /src/termuxgui/oo/framelayout.py: -------------------------------------------------------------------------------- 1 | from typing import Optional, Literal 2 | 3 | import termuxgui as tg 4 | 5 | from termuxgui.activity import Activity 6 | from termuxgui.oo.viewgroup import ViewGroup 7 | 8 | 9 | class FrameLayout(ViewGroup, tg.FrameLayout): 10 | """This represents a FrameLayout.""" 11 | 12 | def __init__(self, activity: Activity, parent: Optional[ViewGroup] = None, 13 | visibility: Optional[Literal[0, 1, 2]] = None): 14 | tg.FrameLayout.__init__(self, activity, parent, visibility) 15 | ViewGroup.__init__(self, activity, self.id, parent) 16 | -------------------------------------------------------------------------------- /src/termuxgui/oo/gridlayout.py: -------------------------------------------------------------------------------- 1 | from typing import Optional, Literal 2 | 3 | import termuxgui as tg 4 | 5 | from termuxgui.activity import Activity 6 | from termuxgui.oo.viewgroup import ViewGroup 7 | 8 | 9 | class GridLayout(ViewGroup, tg.GridLayout): 10 | """This represents a GridLayout.""" 11 | 12 | def __init__(self, activity: Activity, rows: int, cols: int, parent: Optional[ViewGroup] = None, 13 | visibility: Optional[Literal[0, 1, 2]] = None): 14 | tg.GridLayout.__init__(self, activity, rows, cols, parent, visibility) 15 | ViewGroup.__init__(self, activity, self.id, parent) 16 | -------------------------------------------------------------------------------- /src/termuxgui/oo/textview.py: -------------------------------------------------------------------------------- 1 | from typing import Optional, Literal 2 | 3 | import termuxgui as tg 4 | 5 | from termuxgui.oo.view import View 6 | 7 | 8 | class TextView(View, tg.TextView): 9 | """This represents a TextView.""" 10 | 11 | def __init__(self, activity: tg.Activity, text: str, parent: Optional[View] = None, selectabletext: bool = False, 12 | clickablelinks: bool = False, visibility: Optional[Literal[0, 1, 2]] = None): 13 | tg.TextView.__init__(self, activity, text, parent, selectabletext, clickablelinks, visibility) 14 | View.__init__(self, activity, self.id, parent) 15 | -------------------------------------------------------------------------------- /src/termuxgui/oo/linearlayout.py: -------------------------------------------------------------------------------- 1 | from typing import Optional, Literal 2 | 3 | import termuxgui as tg 4 | 5 | from termuxgui.activity import Activity 6 | from termuxgui.oo.viewgroup import ViewGroup 7 | 8 | 9 | class LinearLayout(ViewGroup, tg.LinearLayout): 10 | """This represents a LinearLayout.""" 11 | 12 | def __init__(self, activity: Activity, parent: Optional[ViewGroup] = None, vertical: bool = True, 13 | visibility: Optional[Literal[0, 1, 2]] = None): 14 | tg.LinearLayout.__init__(self, activity, parent, vertical, visibility) 15 | ViewGroup.__init__(self, activity, self.id, parent) 16 | -------------------------------------------------------------------------------- /src/termuxgui/oo/swiperefreshlayout.py: -------------------------------------------------------------------------------- 1 | from typing import Optional, Literal 2 | 3 | import termuxgui as tg 4 | 5 | from termuxgui.oo.view import View 6 | from termuxgui.activity import Activity 7 | from termuxgui.oo.viewgroup import ViewGroup 8 | 9 | 10 | class SwipeRefreshLayout(ViewGroup, tg.SwipeRefreshLayout): 11 | """This represents a SwipeRefreshLayout.""" 12 | 13 | def __init__(self, activity: Activity, parent: Optional[View] = None, 14 | visibility: Optional[Literal[0, 1, 2]] = None): 15 | tg.SwipeRefreshLayout.__init__(self, activity, parent, visibility) 16 | ViewGroup.__init__(self, activity, self.id, parent) 17 | 18 | -------------------------------------------------------------------------------- /src/termuxgui/space.py: -------------------------------------------------------------------------------- 1 | from typing import Optional, Literal 2 | 3 | from termuxgui.activity import Activity 4 | from termuxgui.view import View 5 | 6 | 7 | class Space(View): 8 | """This represents a Space. You can use this to create empty space in your layout.""" 9 | 10 | def __init__(self, activity: Activity, parent: Optional[View] = None, 11 | visibility: Optional[Literal[0, 1, 2]] = None): 12 | args = {"aid": activity.aid, "visibility": visibility} 13 | if parent is not None: 14 | args["parent"] = parent.id 15 | View.__init__(self, activity, activity.c.send_read_msg({"method": "createSpace", "params": args})) 16 | -------------------------------------------------------------------------------- /src/termuxgui/framelayout.py: -------------------------------------------------------------------------------- 1 | from typing import Optional, Literal 2 | 3 | from termuxgui.view import View 4 | from termuxgui.activity import Activity 5 | from termuxgui.viewgroup import ViewGroup 6 | 7 | 8 | class FrameLayout(ViewGroup): 9 | """This represents a FrameLayout.""" 10 | 11 | def __init__(self, activity: Activity, parent: Optional[View] = None, 12 | visibility: Optional[Literal[0, 1, 2]] = None): 13 | args = {"aid": activity.aid, "visibility": visibility} 14 | if parent is not None: 15 | args["parent"] = parent.id 16 | ViewGroup.__init__(self, activity, activity.c.send_read_msg({"method": "createFrameLayout", "params": args})) 17 | -------------------------------------------------------------------------------- /src/termuxgui/oo/radiogroup.py: -------------------------------------------------------------------------------- 1 | from typing import Optional, Literal 2 | 3 | import termuxgui as tg 4 | from termuxgui.oo.view import View 5 | from termuxgui.oo.viewgroup import ViewGroup 6 | 7 | 8 | class RadioGroup(ViewGroup, tg.RadioGroup): 9 | """This represents a RadioGroup. 10 | 11 | Only one RadioButton inside a RadioGroup can be checked at once, and the RadioGroup emits events when the checked button has changed.""" 12 | 13 | def __init__(self, activity: tg.Activity, parent: Optional[View] = None, 14 | visibility: Optional[Literal[0, 1, 2]] = None): 15 | tg.RadioGroup.__init__(self, activity, parent, visibility) 16 | ViewGroup.__init__(self, activity, self.id, parent) 17 | -------------------------------------------------------------------------------- /src/termuxgui/task.py: -------------------------------------------------------------------------------- 1 | from termuxgui.connection import Connection 2 | 3 | 4 | class Task: 5 | """This represents an Android Task. It is automatically created with the Activity.""" 6 | 7 | def __init__(self, connection: Connection, tid: int): 8 | self.c = connection 9 | self.tid = tid 10 | 11 | def finish(self): 12 | """Finishes this Task.""" 13 | self.c.send_msg({"method": "finishTask", "params": {"tid": self.tid}}) 14 | 15 | def bringtofront(self): 16 | """Bring this Task to the front and make it visible to the user. 17 | Might require "overlay over other apps" permission.""" 18 | self.c.send_msg({"method": "bringTaskToFront", "params": {"tid": self.tid}}) 19 | -------------------------------------------------------------------------------- /setup.cfg: -------------------------------------------------------------------------------- 1 | [metadata] 2 | name = termuxgui 3 | version = 0.1.6 4 | author = Tarek Sander 5 | description = Python bindings for the Termux:GUI plugin. 6 | long_description = file: README.md 7 | long_description_content_type = text/markdown 8 | url = https://github.com/tareksander/termux-gui-python-bindings 9 | project_urls = 10 | Bug Tracker = https://github.com/tareksander/termux-gui-python-bindings/issues 11 | classifiers = 12 | Programming Language :: Python :: 3 13 | License :: OSI Approved :: Mozilla Public License 2.0 (MPL 2.0) 14 | Operating System :: Other OS 15 | 16 | [options] 17 | package_dir = 18 | = src 19 | packages = find: 20 | python_requires = >=3.10 21 | 22 | [options.packages.find] 23 | where = src 24 | -------------------------------------------------------------------------------- /src/termuxgui/button.py: -------------------------------------------------------------------------------- 1 | from typing import Optional, Literal 2 | 3 | from termuxgui.activity import Activity 4 | from termuxgui.textview import TextView 5 | from termuxgui.view import View 6 | 7 | 8 | class Button(TextView): 9 | """This represents a Button.""" 10 | 11 | def __init__(self, activity: Activity, text: str, parent: Optional[View] = None, allcaps: bool = False, 12 | visibility: Optional[Literal[0, 1, 2]] = None): 13 | args = {"aid": activity.aid, "text": text, "allcaps": allcaps, "visibility": visibility} 14 | if parent is not None: 15 | args["parent"] = parent.id 16 | View.__init__(self, activity, activity.c.send_read_msg({"method": "createButton", "params": args})) 17 | -------------------------------------------------------------------------------- /src/termuxgui/gridlayout.py: -------------------------------------------------------------------------------- 1 | from typing import Optional, Literal 2 | 3 | from termuxgui.view import View 4 | from termuxgui.activity import Activity 5 | from termuxgui.viewgroup import ViewGroup 6 | 7 | 8 | class GridLayout(ViewGroup): 9 | """This represents a GridLayout.""" 10 | 11 | def __init__(self, activity: Activity, rows: int, cols: int, parent: Optional[View] = None, 12 | visibility: Optional[Literal[0, 1, 2]] = None): 13 | args = {"aid": activity.aid, "rows": rows, "cols": cols, "visibility": visibility} 14 | if parent is not None: 15 | args["parent"] = parent.id 16 | ViewGroup.__init__(self, activity, activity.c.send_read_msg({"method": "createGridLayout", "params": args})) 17 | -------------------------------------------------------------------------------- /src/termuxgui/linearlayout.py: -------------------------------------------------------------------------------- 1 | from typing import Optional, Literal 2 | 3 | from termuxgui.activity import Activity 4 | from termuxgui.view import View 5 | from termuxgui.viewgroup import ViewGroup 6 | 7 | 8 | class LinearLayout(ViewGroup): 9 | """This represents a LinearLayout.""" 10 | 11 | def __init__(self, activity: Activity, parent: Optional[View] = None, vertical: bool = True, 12 | visibility: Optional[Literal[0, 1, 2]] = None): 13 | args = {"aid": activity.aid, "vertical": vertical, "visibility": visibility} 14 | if parent is not None: 15 | args["parent"] = parent.id 16 | ViewGroup.__init__(self, activity, activity.c.send_read_msg({"method": "createLinearLayout", "params": args})) 17 | -------------------------------------------------------------------------------- /src/termuxgui/checkbox.py: -------------------------------------------------------------------------------- 1 | from typing import Optional, Literal 2 | 3 | from termuxgui.activity import Activity 4 | from termuxgui.compoundbutton import CompoundButton 5 | from termuxgui.view import View 6 | 7 | 8 | class Checkbox(CompoundButton): 9 | """This represents a CheckBox.""" 10 | 11 | def __init__(self, activity: Activity, text: str, parent: Optional[View] = None, checked: bool = False, 12 | visibility: Optional[Literal[0, 1, 2]] = None): 13 | args = {"aid": activity.aid, "text": text, "checked": checked, "visibility": visibility} 14 | if parent is not None: 15 | args["parent"] = parent.id 16 | self.checked = checked 17 | View.__init__(self, activity, activity.c.send_read_msg({"method": "createCheckbox", "params": args})) 18 | -------------------------------------------------------------------------------- /src/termuxgui/togglebutton.py: -------------------------------------------------------------------------------- 1 | from typing import Optional, Literal 2 | 3 | from termuxgui.view import View 4 | from termuxgui.activity import Activity 5 | from termuxgui.compoundbutton import CompoundButton 6 | 7 | 8 | class ToggleButton(CompoundButton): 9 | """This represents a ToggleButton.""" 10 | 11 | def __init__(self, activity: Activity, parent: Optional[View] = None, checked: bool = False, 12 | visibility: Optional[Literal[0, 1, 2]] = None): 13 | args = {"aid": activity.aid, "checked": checked, "visibility": visibility} 14 | if parent is not None: 15 | args["parent"] = parent.id 16 | self.checked = checked 17 | CompoundButton.__init__(self, activity, activity.c.send_read_msg({"method": "createToggleButton", "params": args})) 18 | -------------------------------------------------------------------------------- /src/termuxgui/switch.py: -------------------------------------------------------------------------------- 1 | from typing import Optional, Literal 2 | 3 | from termuxgui.view import View 4 | from termuxgui.activity import Activity 5 | from termuxgui.compoundbutton import CompoundButton 6 | 7 | 8 | class Switch(CompoundButton): 9 | """This represents a Switch.""" 10 | 11 | def __init__(self, activity: Activity, text: str, parent: Optional[View] = None, checked: bool = False, 12 | visibility: Optional[Literal[0, 1, 2]] = None): 13 | args = {"aid": activity.aid, "text": text, "checked": checked, "visibility": visibility} 14 | if parent is not None: 15 | args["parent"] = parent.id 16 | self.checked = checked 17 | CompoundButton.__init__(self, activity, activity.c.send_read_msg({"method": "createSwitch", "params": args})) 18 | -------------------------------------------------------------------------------- /src/termuxgui/oo/horizontalscrollview.py: -------------------------------------------------------------------------------- 1 | from typing import Optional, Literal 2 | 3 | import termuxgui as tg 4 | 5 | from termuxgui.activity import Activity 6 | from termuxgui.oo.framelayout import FrameLayout 7 | from termuxgui.oo.viewgroup import ViewGroup 8 | 9 | 10 | class HorizontalScrollView(FrameLayout, tg.HorizontalScrollView): 11 | """This represents a HorizontalScrollView.""" 12 | 13 | def __init__(self, activity: Activity, parent: Optional[ViewGroup] = None, fillviewport: bool = False, 14 | snapping: bool = False, nobar: bool = False, 15 | visibility: Optional[Literal[0, 1, 2]] = None): 16 | tg.HorizontalScrollView.__init__(self, activity, parent, fillviewport, snapping, nobar, visibility) 17 | ViewGroup.__init__(self, activity, self.id, parent) 18 | -------------------------------------------------------------------------------- /src/termuxgui/radiobutton.py: -------------------------------------------------------------------------------- 1 | from typing import Optional, Literal 2 | 3 | from termuxgui.view import View 4 | from termuxgui.activity import Activity 5 | from termuxgui.compoundbutton import CompoundButton 6 | 7 | 8 | class RadioButton(CompoundButton): 9 | """This represents a RadioButton.""" 10 | 11 | def __init__(self, activity: Activity, text: str, parent: Optional[View] = None, checked: bool = False, 12 | visibility: Optional[Literal[0, 1, 2]] = None): 13 | args = {"aid": activity.aid, "text": text, "checked": checked, "visibility": visibility} 14 | if parent is not None: 15 | args["parent"] = parent.id 16 | self.checked = checked 17 | CompoundButton.__init__(self, activity, activity.c.send_read_msg({"method": "createRadioButton", "params": args})) 18 | -------------------------------------------------------------------------------- /src/termuxgui/oo/nestedscrollview.py: -------------------------------------------------------------------------------- 1 | from typing import Optional, Literal 2 | 3 | import termuxgui as tg 4 | 5 | from termuxgui.view import View 6 | from termuxgui.activity import Activity 7 | from termuxgui.oo.framelayout import FrameLayout 8 | from termuxgui.oo.viewgroup import ViewGroup 9 | 10 | 11 | class NestedScrollView(FrameLayout, tg.NestedScrollView): 12 | """This represents a NestedScrollView.""" 13 | 14 | def __init__(self, activity: Activity, parent: Optional[View] = None, fillviewport: bool = False, 15 | snapping: bool = False, nobar: bool = False, 16 | visibility: Optional[Literal[0, 1, 2]] = None): 17 | tg.NestedScrollView.__init__(self, activity, parent, fillviewport, snapping, nobar, visibility) 18 | ViewGroup.__init__(self, activity, self.id, parent) 19 | 20 | -------------------------------------------------------------------------------- /src/termuxgui/oo/view.py: -------------------------------------------------------------------------------- 1 | from abc import ABC 2 | from typing import Optional, TYPE_CHECKING 3 | 4 | import termuxgui as tg 5 | from termuxgui.activity import Activity 6 | 7 | 8 | class View(tg.View, ABC): 9 | """This represents a generic View.""" 10 | 11 | def __init__(self, activity: Activity, id: int, parent: Optional['termuxgui.oo.viewgroup.ViewGroup']): 12 | tg.View.__init__(self, activity, id) 13 | self.parent = parent 14 | if self.parent: 15 | parent.views.append(self) 16 | else: 17 | activity.root = self 18 | 19 | def delete(self): 20 | """Deletes this View from the layout.""" 21 | if self.parent: 22 | self.parent.views.remove(self) 23 | tg.View.delete(self) 24 | 25 | 26 | if TYPE_CHECKING: 27 | import termuxgui.oo.viewgroup 28 | -------------------------------------------------------------------------------- /src/termuxgui/radiogroup.py: -------------------------------------------------------------------------------- 1 | from typing import Optional, Literal 2 | 3 | from termuxgui.view import View 4 | from termuxgui.activity import Activity 5 | from termuxgui.linearlayout import LinearLayout 6 | from termuxgui.viewgroup import ViewGroup 7 | 8 | 9 | class RadioGroup(LinearLayout): 10 | """This represents a RadioGroup. 11 | 12 | Only one RadioButton inside a RadioGroup can be checked at once, and the RadioGroup emits events when the checked button has changed.""" 13 | 14 | def __init__(self, activity: Activity, parent: Optional[View] = None, 15 | visibility: Optional[Literal[0, 1, 2]] = None): 16 | args = {"aid": activity.aid, "visibility": visibility} 17 | if parent is not None: 18 | args["parent"] = parent.id 19 | ViewGroup.__init__(self, activity, activity.c.send_read_msg({"method": "createRadioGroup", "params": args})) 20 | -------------------------------------------------------------------------------- /tutorial/webview.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | 3 | import time 4 | import termuxgui as tg 5 | import sys 6 | 7 | with tg.Connection() as c: 8 | a = tg.Activity(c) 9 | 10 | # create a WebView 11 | wv = tg.WebView(a) 12 | 13 | # Set the webpage content 14 | wv.setdata("
This is a paragraph
") 15 | 16 | time.sleep(3) 17 | 18 | # Load a web page via a URL 19 | wv.loaduri("https://www.google.com") 20 | 21 | time.sleep(3) 22 | 23 | # Prompt the user to allow Javascript 24 | wv.allowjavascript(True) 25 | 26 | # Run Javascript in the page 27 | wv.evaluatejs('''document.body.innerHTML = "Set via Javascript
"''') 28 | 29 | for ev in c.events(): 30 | if ev.type == tg.Event.destroy and ev.value["finishing"]: 31 | sys.exit() 32 | -------------------------------------------------------------------------------- /src/termuxgui/progressbar.py: -------------------------------------------------------------------------------- 1 | from typing import Optional, Literal 2 | 3 | from termuxgui.activity import Activity 4 | from termuxgui.view import View 5 | 6 | 7 | class ProgressBar(View): 8 | """This represents a ProgressBar.""" 9 | 10 | def __init__(self, activity: Activity, parent: Optional[View] = None, 11 | visibility: Optional[Literal[0, 1, 2]] = None): 12 | args = {"aid": activity.aid, "visibility": visibility} 13 | if parent is not None: 14 | args["parent"] = parent.id 15 | View.__init__(self, activity, activity.c.send_read_msg({"method": "createProgressBar", "params": args})) 16 | 17 | def setprogress(self, progress: int): 18 | """Sets the progress of the ProgressBar. The progress has to be an integer from 0 to 100 (inclusive).""" 19 | self.a.c.send_msg({"method": "setProgress", "params": {"aid": self.a.aid, "id": self.id, "progress": progress}}) 20 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Termux:GUI Python Bindings 2 | A Python library to interact with the Termux:GUI plugin. 3 | 4 | See [here](https://github.com/tareksander/termux-gui-python-bindings/blob/main/TUTORIAL.md) for a tutorial 5 | and [here](https://github.com/tareksander/termux-gui-python-bindings/blob/main/TUTORIAL_OOP.md) for using the more object-oriented subpackage. 6 | 7 | There is also [documentation](https://tareksander.github.io/termux-gui-python-bindings/index.html) generated from the docstrings. 8 | 9 | 10 | ### Installing and updating: 11 | Just use `pip install termuxgui` to install from pypi. 12 | 13 | 14 | ### License 15 | 16 | The license is the [Mozilla Public License 2.0](https://www.mozilla.org/en-US/MPL/2.0/). 17 | TL;DR: You can use this library in your own projects, regardless of the license you choose for it. Modifications to this library have to be published under the MPL 2.0 (or a GNU license in some cases) though. 18 | -------------------------------------------------------------------------------- /src/termuxgui/oo/edittext.py: -------------------------------------------------------------------------------- 1 | from typing import Optional, Literal 2 | 3 | import termuxgui as tg 4 | 5 | from termuxgui.oo.view import View 6 | 7 | 8 | class EditText(View, tg.EditText): 9 | """This represents an EditText.""" 10 | 11 | def __init__(self, activity: tg.Activity, text: str, parent: Optional[View] = None, singleline: bool = False, 12 | line: bool = True, blockinput: bool = False, 13 | inputtype: Literal["text", "textMultiLine", "phone", "date", "time", "datetime", "number", 14 | "numberDecimal", "numberPassword", "numberSigned", "numberDecimalSigned", 15 | "textEmailAddress", "textPassword"] = "text", 16 | visibility: Optional[Literal[0, 1, 2]] = None): 17 | tg.EditText.__init__(self, activity, text, parent, singleline, line, blockinput, inputtype, visibility) 18 | View.__init__(self, activity, self.id, parent) 19 | 20 | -------------------------------------------------------------------------------- /src/termuxgui/spinner.py: -------------------------------------------------------------------------------- 1 | from typing import Optional, List, Literal 2 | 3 | from termuxgui.activity import Activity 4 | from termuxgui.view import View 5 | 6 | 7 | class Spinner(View): 8 | """This represents a Spinner.""" 9 | 10 | def __init__(self, activity: Activity, parent: Optional[View] = None, 11 | visibility: Optional[Literal[0, 1, 2]] = None): 12 | args = {"aid": activity.aid, "visibility": visibility} 13 | if parent is not None: 14 | args["parent"] = parent.id 15 | View.__init__(self, activity, activity.c.send_read_msg({"method": "createSpinner", "params": args})) 16 | 17 | def setlist(self, list: List[str]): 18 | """Sets the list of items displayed in the Spinner.""" 19 | self.a.c.send_msg({"method": "setList", "params": {"aid": self.a.aid, "id": self.id, "list": list}}) 20 | 21 | def selectitem(self, item: int): 22 | """Sets the selected item of the Spinner.""" 23 | self.a.c.send_msg({"method": "selectItem", "params": {"aid": self.a.aid, "id": self.id, "item": item}}) 24 | -------------------------------------------------------------------------------- /src/termuxgui/swiperefreshlayout.py: -------------------------------------------------------------------------------- 1 | from typing import Optional, Literal 2 | 3 | from termuxgui.view import View 4 | from termuxgui.activity import Activity 5 | from termuxgui.viewgroup import ViewGroup 6 | 7 | 8 | class SwipeRefreshLayout(ViewGroup): 9 | """This represents a SwipeRefreshLayout.""" 10 | 11 | def __init__(self, activity: Activity, parent: Optional[View] = None, 12 | visibility: Optional[Literal[0, 1, 2]] = None): 13 | args = {"aid": activity.aid, "visibility": visibility} 14 | if parent is not None: 15 | args["parent"] = parent.id 16 | ViewGroup.__init__(self, activity, 17 | activity.c.send_read_msg({"method": "createSwipeRefreshLayout", "params": args})) 18 | 19 | def setrefreshing(self, refreshing: bool): 20 | """Sets whether the SwipeRefreshLayout displays the refresh animation. 21 | 22 | You have to call this with False when you refreshed the contents.""" 23 | self.a.c.send_msg( 24 | {"method": "setRefreshing", "params": {"aid": self.a.aid, "id": self.id, "refresh": refreshing}}) 25 | -------------------------------------------------------------------------------- /src/termuxgui/compoundbutton.py: -------------------------------------------------------------------------------- 1 | from termuxgui.activity import Activity 2 | from termuxgui.button import Button 3 | from termuxgui.event import Event 4 | from termuxgui.view import View 5 | 6 | 7 | class CompoundButton(Button): 8 | """This represents a CompoundButton. 9 | 10 | This class doesn't correspond to a particular View, it is used to provide common methods for all CompoundButtons.""" 11 | 12 | def __init__(self, activity: Activity, id: int): 13 | View.__init__(self, activity, id) 14 | self.checked = False 15 | 16 | def handleevent(self, e: Event): 17 | """Use this to let the CompoundButton track whether it is checked or not. Just pass every Event here.""" 18 | if e.type == Event.click and e.aid == self.a.aid and e.id == self.id: 19 | self.checked = e.value["set"] 20 | View.handleevent(self, e) 21 | 22 | def setchecked(self, checked: bool): 23 | """Explicitly set the checked status of this CompoundButton.""" 24 | self.checked = checked 25 | self.a.c.send_msg({"method": "setChecked", "params": {"aid": self.a.aid, "id": self.id, "checked": checked}}) 26 | -------------------------------------------------------------------------------- /docsource/conf.py: -------------------------------------------------------------------------------- 1 | # Configuration file for the Sphinx documentation builder. 2 | # 3 | # For the full list of built-in configuration values, see the documentation: 4 | # https://www.sphinx-doc.org/en/master/usage/configuration.html 5 | 6 | # -- Project information ----------------------------------------------------- 7 | # https://www.sphinx-doc.org/en/master/usage/configuration.html#project-information 8 | 9 | import sys 10 | import os 11 | 12 | sys.path.append(os.path.dirname(os.getcwd())+"/src/") 13 | 14 | project = 'termuxgui' 15 | copyright = '2022, Tarek Sander' 16 | author = 'Tarek Sander' 17 | release = '0.1.5' 18 | 19 | # -- General configuration --------------------------------------------------- 20 | # https://www.sphinx-doc.org/en/master/usage/configuration.html#general-configuration 21 | 22 | extensions = [ 23 | 'sphinx.ext.autodoc', 24 | ] 25 | 26 | 27 | templates_path = ['_templates'] 28 | exclude_patterns = [] 29 | 30 | 31 | 32 | # -- Options for HTML output ------------------------------------------------- 33 | # https://www.sphinx-doc.org/en/master/usage/configuration.html#options-for-html-output 34 | 35 | html_theme = 'nature' 36 | html_static_path = ['_static'] 37 | -------------------------------------------------------------------------------- /src/termuxgui/tablayout.py: -------------------------------------------------------------------------------- 1 | from typing import Optional, List, Literal 2 | 3 | from termuxgui.view import View 4 | from termuxgui.activity import Activity 5 | from termuxgui.horizontalscrollview import HorizontalScrollView 6 | from termuxgui.viewgroup import ViewGroup 7 | 8 | 9 | class TabLayout(HorizontalScrollView): 10 | """This represents a TabLayout.""" 11 | 12 | def __init__(self, activity: Activity, parent: Optional[View] = None, 13 | visibility: Optional[Literal[0, 1, 2]] = None): 14 | args = {"aid": activity.aid, "visibility": visibility} 15 | if parent is not None: 16 | args["parent"] = parent.id 17 | ViewGroup.__init__(self, activity, activity.c.send_read_msg({"method": "createTabLayout", "params": args})) 18 | 19 | def setlist(self, list: List[str]): 20 | """Sets the list tabs.""" 21 | self.a.c.send_msg({"method": "setList", "params": {"aid": self.a.aid, "id": self.id, "list": list}}) 22 | 23 | def selecttab(self, tab: int): 24 | """Selects a tab in the TabLayout. tab is the index of the tab to select, starting at 0.""" 25 | self.a.c.send_msg({"method": "selectTab", "params": {"aid": self.a.aid, "id": self.id, "tab": tab}}) 26 | 27 | -------------------------------------------------------------------------------- /.github/workflows/python-publish.yml: -------------------------------------------------------------------------------- 1 | # This workflow will upload a Python Package using Twine when a release is created 2 | # For more information see: https://help.github.com/en/actions/language-and-framework-guides/using-python-with-github-actions#publishing-to-package-registries 3 | 4 | # This workflow uses actions that are not certified by GitHub. 5 | # They are provided by a third-party and are governed by 6 | # separate terms of service, privacy policy, and support 7 | # documentation. 8 | 9 | name: Upload Python Package 10 | 11 | on: 12 | release: 13 | types: [published] 14 | 15 | permissions: 16 | contents: read 17 | 18 | jobs: 19 | deploy: 20 | 21 | runs-on: ubuntu-latest 22 | 23 | steps: 24 | - uses: actions/checkout@v3 25 | - name: Set up Python 26 | uses: actions/setup-python@v3 27 | with: 28 | python-version: '3.x' 29 | - name: Install dependencies 30 | run: | 31 | python -m pip install --upgrade pip 32 | pip install build 33 | - name: Build package 34 | run: python -m build 35 | - name: Publish package 36 | uses: pypa/gh-action-pypi-publish@27b31702a0e7fc50959f5ad993c78deac1bdfc29 37 | with: 38 | user: __token__ 39 | password: ${{ secrets.PYPI_API_TOKEN }} 40 | -------------------------------------------------------------------------------- /tutorial/linearlayout1.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | 3 | import termuxgui as tg 4 | import time 5 | 6 | with tg.Connection() as c: 7 | a = tg.Activity(c) 8 | 9 | layout = tg.LinearLayout(a) 10 | 11 | # Create 3 TextViews 12 | tv1 = tg.TextView(a, "TextView 1", layout) 13 | tv2 = tg.TextView(a, "TextView 2", layout) 14 | tv3 = tg.TextView(a, "TextView 3", layout) 15 | 16 | # Now we make them only occupy the space they need. 17 | # We first have to set the layout weight to 0 to prevent them from using the free space. 18 | tv1.setlinearlayoutparams(0) 19 | tv2.setlinearlayoutparams(0) 20 | tv3.setlinearlayoutparams(0) 21 | 22 | # Then we have to set the height to "WRAP_CONTENT". 23 | # You can specify width and height in 3 ways: as an integer in dp, "WRAP_CONTENT" and "MATCH_PARENT". 24 | # "WRAP_CONTENT" makes a View occupy only the space it needs. 25 | # "MATCH_PARENT" makes a view as large as the parent Layout in that dimension. 26 | # To prevent mistyping, "WRAP_CONTENT" and "MATCH_PARENT" are also defined as constants in the View class. 27 | 28 | # Since the TextViews are displayed in a list, we set the height to "WRAP_CONTENT". 29 | tv1.setheight(tg.View.WRAP_CONTENT) 30 | tv2.setheight(tg.View.WRAP_CONTENT) 31 | tv3.setheight(tg.View.WRAP_CONTENT) 32 | 33 | time.sleep(5) 34 | -------------------------------------------------------------------------------- /src/termuxgui/edittext.py: -------------------------------------------------------------------------------- 1 | from typing import Optional, Literal 2 | 3 | from termuxgui.activity import Activity 4 | from termuxgui.textview import TextView 5 | from termuxgui.view import View 6 | 7 | 8 | class EditText(TextView): 9 | """This represents an EditText.""" 10 | 11 | def __init__(self, activity: Activity, text: str, parent: Optional[View] = None, singleline: bool = False, 12 | line: bool = True, blockinput: bool = False, 13 | inputtype: Literal["text", "textMultiLine", "phone", "date", "time", "datetime", "number", 14 | "numberDecimal", "numberPassword", "numberSigned", "numberDecimalSigned", 15 | "textEmailAddress", "textPassword"] = "text", 16 | visibility: Optional[Literal[0, 1, 2]] = None): 17 | args = {"aid": activity.aid, "text": text, "singleline": singleline, "line": line, "blockinput": blockinput, 18 | "type": inputtype, "visibility": visibility} 19 | if parent is not None: 20 | args["parent"] = parent.id 21 | View.__init__(self, activity, activity.c.send_read_msg({"method": "createEditText", "params": args})) 22 | 23 | def showcursor(self, show: bool): 24 | """Sets whether the cursor position should be shown.""" 25 | self.a.c.send_msg({"method": "showCursor", "params": {"aid": self.a.aid, "id": self.id, "show": show}}) 26 | -------------------------------------------------------------------------------- /src/termuxgui/horizontalscrollview.py: -------------------------------------------------------------------------------- 1 | from typing import Optional, List, Literal 2 | 3 | from termuxgui.view import View 4 | from termuxgui.activity import Activity 5 | from termuxgui.framelayout import FrameLayout 6 | from termuxgui.viewgroup import ViewGroup 7 | 8 | 9 | class HorizontalScrollView(FrameLayout): 10 | """This represents a HorizontalScrollView.""" 11 | 12 | def __init__(self, activity: Activity, parent: Optional[View] = None, fillviewport: bool = False, 13 | snapping: bool = False, nobar: bool = False, 14 | visibility: Optional[Literal[0, 1, 2]] = None): 15 | args = {"aid": activity.aid, "fillviewport": fillviewport, "snapping": snapping, "nobar": nobar, 16 | "visibility": visibility} 17 | if parent is not None: 18 | args["parent"] = parent.id 19 | ViewGroup.__init__(self, activity, activity.c.send_read_msg({"method": "createHorizontalScrollView", "params": args})) 20 | 21 | def getscrollposition(self) -> List[int]: 22 | """Gets the x and x scroll positions.""" 23 | return self.a.c.send_read_msg({"method": "getScrollPosition", "params": {"aid": self.a.aid, "id": self.id}}) 24 | 25 | def setscrollposition(self, x: int, y: int, smooth: bool = True): 26 | """Sets the x and x scroll positions. smooth specifies whether is's a smooth scoll or not.""" 27 | self.a.c.send_msg({"method": "setScrollPosition", "params": {"aid": self.a.aid, "id": self.id, "x": x, "y": y, "soft": smooth}}) 28 | -------------------------------------------------------------------------------- /src/termuxgui/nestedscrollview.py: -------------------------------------------------------------------------------- 1 | from typing import Optional, List, Literal 2 | 3 | from termuxgui.view import View 4 | from termuxgui.activity import Activity 5 | from termuxgui.framelayout import FrameLayout 6 | from termuxgui.viewgroup import ViewGroup 7 | 8 | 9 | class NestedScrollView(FrameLayout): 10 | """This represents a NestedScrollView.""" 11 | 12 | def __init__(self, activity: Activity, parent: Optional[View] = None, fillviewport: bool = False, 13 | snapping: bool = False, nobar: bool = False, 14 | visibility: Optional[Literal[0, 1, 2]] = None): 15 | args = {"aid": activity.aid, "fillviewport": fillviewport, "snapping": snapping, "nobar": nobar, 16 | "visibility": visibility} 17 | if parent is not None: 18 | args["parent"] = parent.id 19 | ViewGroup.__init__(self, activity, 20 | activity.c.send_read_msg({"method": "createNestedScrollView", "params": args})) 21 | 22 | def getscrollposition(self) -> List[int]: 23 | """Gets the x and x scroll positions.""" 24 | return self.a.c.send_read_msg({"method": "getScrollPosition", "params": {"aid": self.a.aid, "id": self.id}}) 25 | 26 | def setscrollposition(self, x: int, y: int, smooth: bool = True): 27 | """Sets the x and x scroll positions. smooth specifies whether it's a smooth scroll or not.""" 28 | self.a.c.send_msg({"method": "setScrollPosition", 29 | "params": {"aid": self.a.aid, "id": self.id, "x": x, "y": y, "soft": smooth}}) 30 | -------------------------------------------------------------------------------- /src/termuxgui/imageview.py: -------------------------------------------------------------------------------- 1 | import base64 2 | from typing import Optional, Literal 3 | 4 | from termuxgui.buffer import Buffer 5 | from termuxgui.activity import Activity 6 | from termuxgui.view import View 7 | 8 | 9 | class ImageView(View): 10 | """This represents an ImageView.""" 11 | 12 | def __init__(self, activity: Activity, parent: Optional[View] = None, 13 | visibility: Optional[Literal[0, 1, 2]] = None): 14 | args = {"aid": activity.aid, "visibility": visibility} 15 | if parent is not None: 16 | args["parent"] = parent.id 17 | View.__init__(self, activity, activity.c.send_read_msg({"method": "createImageView", "params": args})) 18 | 19 | def setimage(self, img: bytes): 20 | """Sets the image of the ImageView. 21 | The image has to be a bytes object containing the image in png or jpeg format.""" 22 | self.a.c.send_msg({"method": "setImage", "params": {"aid": self.a.aid, "id": self.id, 23 | "img": base64.standard_b64encode(img).decode("ascii")}}) 24 | 25 | def setbuffer(self, b: Buffer): 26 | """Makes the ImageView use a shared buffer as the image source.""" 27 | self.a.c.send_msg({"method": "setBuffer", "params": {"aid": self.a.aid, "id": self.id, "bid": b.bid}}) 28 | 29 | def refresh(self): 30 | """Redraws the ImageView. You have to use this after blitting the Buffer when using a buffer.""" 31 | self.a.c.send_msg({"method": "refreshImageView", "params": {"aid": self.a.aid, "id": self.id}}) 32 | -------------------------------------------------------------------------------- /tutorial/linearlayout2.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | 3 | import termuxgui as tg 4 | import time 5 | 6 | with tg.Connection() as c: 7 | a = tg.Activity(c) 8 | 9 | layout = tg.LinearLayout(a) 10 | 11 | # Create 3 TextViews 12 | tv1 = tg.TextView(a, "TextView 1", layout) 13 | tv2 = tg.TextView(a, "TextView 2", layout) 14 | buttons = tg.LinearLayout(a, layout, False) # use False to create this as a horizontal layout 15 | tv3 = tg.TextView(a, "TextView 3", layout) 16 | 17 | # Now we make them only occupy the space they need. 18 | # We first have to set the layout weight to 0 to prevent them from using the free space. 19 | tv1.setlinearlayoutparams(0) 20 | tv2.setlinearlayoutparams(0) 21 | buttons.setlinearlayoutparams(0) 22 | tv3.setlinearlayoutparams(0) 23 | 24 | # Then we have to set the height to "WRAP_CONTENT". 25 | # You can specify width and height in 3 ways: as an integer in dp, "WRAP_CONTENT" and "MATCH_PARENT". 26 | # "WRAP_CONTENT" makes a View occupy only the space it needs. 27 | # "MATCH_PARENT" makes a view as large as the parent layout in that dimension. 28 | 29 | # Since the TextViews are displayed in a list, we set the height to "WRAP_CONTENT". 30 | tv1.setheight(tg.View.WRAP_CONTENT) 31 | tv2.setheight(tg.View.WRAP_CONTENT) 32 | buttons.setheight(tg.View.WRAP_CONTENT) 33 | tv3.setheight(tg.View.WRAP_CONTENT) 34 | 35 | bt1 = tg.Button(a, "Button1", buttons) 36 | bt2 = tg.Button(a, "Button2", buttons) 37 | bt3 = tg.Button(a, "Button3", buttons) 38 | 39 | time.sleep(5) 40 | -------------------------------------------------------------------------------- /tutorial_oop/helloworld.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | 3 | # Some classes like RemoteViews and Buffer are still required from termuxgui, so import both 4 | import termuxgui.oo as tgo 5 | import termuxgui as tg 6 | 7 | 8 | # Layouts can be defined as classes, to make them reusable 9 | class HelloWorldLayout(tgo.LinearLayout): 10 | def __init__(self, activity: tgo.Activity): 11 | # Initialize the LinearLayout as the root Layout 12 | super().__init__(activity) 13 | # define a TextView 14 | tgo.TextView(self.a, "Hello World", self) 15 | # define a Button 16 | b = tgo.Button(self.a, "Click me!", self) 17 | # Also new is the event system: 18 | # You can provide callables as on_* methods which will be called 19 | # if the corresponding Event is triggered on the View. 20 | # The methods get the event and the View as parameters. 21 | b.on_click = lambda e, v: print(e.type, e.value, v.id) 22 | 23 | 24 | # Activities are now classes 25 | class HelloWorldActivity(tgo.Activity): 26 | 27 | def __init__(self, c, t): 28 | super().__init__(c, t) 29 | # Add the Layout to the Activity 30 | HelloWorldLayout(self) 31 | 32 | 33 | with tgo.Connection() as c: 34 | # Activities aren't created directly with the constructor anymore, but with the launch method of the connection 35 | c.launch(HelloWorldActivity) 36 | 37 | # The event loop is build into the connection. 38 | # It automatically quits if there aren't any Activities left. 39 | c.event_loop() 40 | -------------------------------------------------------------------------------- /src/termuxgui/oo/__init__.py: -------------------------------------------------------------------------------- 1 | 2 | __all__ = ["Activity", "Button", "Checkbox", "Connection", "EditText", "FrameLayout", "GridLayout", 3 | "HorizontalScrollView", "ImageView", "LinearLayout", "NestedScrollView","ProgressBar", 4 | "RadioButton", "RadioGroup", "Space", "Spinner","SwipeRefreshLayout", "Switch", 5 | "TabLayout", "TextView", "ToggleButton", "View", "ViewGroup", "WebView"] 6 | 7 | from termuxgui.oo.activity import Activity 8 | from termuxgui.oo.button import Button 9 | from termuxgui.oo.checkbox import Checkbox 10 | from termuxgui.oo.connection import Connection 11 | from termuxgui.oo.edittext import EditText 12 | from termuxgui.oo.framelayout import FrameLayout 13 | from termuxgui.oo.gridlayout import GridLayout 14 | from termuxgui.oo.horizontalscrollview import HorizontalScrollView 15 | from termuxgui.oo.imageview import ImageView 16 | from termuxgui.oo.linearlayout import LinearLayout 17 | from termuxgui.oo.nestedscrollview import NestedScrollView 18 | from termuxgui.oo.progressbar import ProgressBar 19 | from termuxgui.oo.radiobutton import RadioButton 20 | from termuxgui.oo.radiogroup import RadioGroup 21 | from termuxgui.oo.space import Space 22 | from termuxgui.oo.spinner import Spinner 23 | from termuxgui.oo.swiperefreshlayout import SwipeRefreshLayout 24 | from termuxgui.oo.switch import Switch 25 | from termuxgui.oo.tablayout import TabLayout 26 | from termuxgui.oo.textview import TextView 27 | from termuxgui.oo.togglebutton import ToggleButton 28 | from termuxgui.oo.view import View 29 | from termuxgui.oo.viewgroup import ViewGroup 30 | from termuxgui.oo.webview import WebView 31 | 32 | 33 | -------------------------------------------------------------------------------- /src/termuxgui/msg.py: -------------------------------------------------------------------------------- 1 | from json import loads 2 | import array 3 | import socket 4 | from typing import Any, Tuple, Optional 5 | 6 | 7 | def read_msg(s: socket.socket) -> Any: 8 | b = b'' 9 | togo = 4 10 | while togo > 0: 11 | read = s.recv(togo) 12 | b = b + read 13 | togo = togo - len(read) 14 | togo = int.from_bytes(b, "big") 15 | b = b'' 16 | while togo > 0: 17 | read = s.recv(togo) 18 | b = b + read 19 | togo = togo - len(read) 20 | return loads(b.decode("utf-8")) 21 | 22 | 23 | def send_msg(c: socket.socket, msg: str): 24 | m = bytes(msg, "utf-8") 25 | c.sendall((len(m)).to_bytes(4, "big")) 26 | c.sendall(m) 27 | 28 | 29 | def send_read_msg(s: socket.socket, msg: str) -> Any: 30 | send_msg(s, msg) 31 | return read_msg(s) 32 | 33 | 34 | def read_msg_fd(s: socket.socket) -> Tuple[Any, Optional[int]]: 35 | b = b'' 36 | togo = 4 37 | while togo > 0: 38 | read = s.recv(togo) 39 | b = b + read 40 | togo = togo - len(read) 41 | togo = int.from_bytes(b, "big") 42 | b = b'' 43 | fds = array.array("i") 44 | while togo > 0: 45 | read, ancdata, _, _ = s.recvmsg(togo, socket.CMSG_LEN(fds.itemsize)) 46 | for cmsg_level, cmsg_type, cmsg_data in ancdata: 47 | if cmsg_level == socket.SOL_SOCKET and cmsg_type == socket.SCM_RIGHTS: 48 | fds.frombytes(cmsg_data[:len(cmsg_data) - (len(cmsg_data) % fds.itemsize)]) 49 | b = b + read 50 | togo = togo - len(read) 51 | if len(fds) != 0: 52 | return loads(b.decode("utf-8")), fds[0] 53 | else: 54 | return loads(b.decode("utf-8")), None 55 | -------------------------------------------------------------------------------- /tutorial/hellolayout.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | 3 | import termuxgui as tg 4 | import time 5 | 6 | with tg.Connection() as c: 7 | a = tg.Activity(c) 8 | 9 | # For each View or layout you create you can specify the parent Layout to create a hierarchy. 10 | # If you don't specify a parent, it will replace the current root View. 11 | # We first create a LinearLayout as our root View. 12 | root = tg.LinearLayout(a) 13 | 14 | # Then we create a TextView that we will use as a title 15 | title = tg.TextView(a, "Awesome Title", root) 16 | 17 | # We set the font size a bit bigger 18 | title.settextsize(30) 19 | 20 | contenttext = "Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor " \ 21 | "invidunt utlabore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et " \ 22 | "accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata " \ 23 | "sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur " \ 24 | "sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore " \ 25 | "magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo " \ 26 | "dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est " \ 27 | "Lorem ipsum dolor sit amet." 28 | # Now we create a TextView for the main content 29 | content = tg.TextView(a, contenttext, root) 30 | 31 | # And we add a Button at the end 32 | button = tg.Button(a, "Click here!", root) 33 | 34 | # Now we give the Layout priority to our content Textview, so it is bigger than the Button and the title. 35 | content.setlinearlayoutparams(10) 36 | 37 | time.sleep(5) 38 | -------------------------------------------------------------------------------- /src/termuxgui/buffer.py: -------------------------------------------------------------------------------- 1 | from mmap import mmap 2 | import os 3 | from typing import Literal 4 | 5 | import termuxgui.msg as msg 6 | 7 | 8 | class Buffer: 9 | """This represents a raw ARGB888 image buffer. 10 | 11 | This is only available on Android 8.1+. 12 | Buffers consume much memory, so be sure to close any Buffer you don't need any more. 13 | Preferably use "with" to get the memory object of the buffer so it is automatically closed. 14 | The memory object is a shared memory object that can be used like a bytes object or a file object. 15 | You can also directly access the memory object as b.mem. 16 | 17 | A RuntimeError is raised when a Buffer can't be created.""" 18 | 19 | def __init__(self, connection, w: int, h: int, format: Literal["ARGB888"] = "ARGB888"): 20 | self.c = connection 21 | self.c.send_msg({"method": "addBuffer", "params": {"w": w, "h": h, "format": format}}) 22 | ret = msg.read_msg_fd(self.c._main) 23 | if len(ret) == 1: 24 | raise RuntimeError("Could not create Buffer") 25 | self.bid, self.fd = ret 26 | self.mem = mmap(self.fd, w * h * 4) 27 | 28 | def __enter__(self): 29 | return self.mem 30 | 31 | def __exit__(self, type, value, traceback): 32 | self.remove() 33 | return False 34 | 35 | def remove(self): 36 | """Removes this buffer, freeing the memory.""" 37 | self.c.send_msg({"method": "deleteBuffer", "params": {"bid": self.bid}}) 38 | self.mem.close() 39 | os.close(self.fd) 40 | 41 | def blit(self): 42 | """Blits the buffer to the underlying image in the plugin. 43 | To update ImageViews using this buffer, they have to be refreshed afterwards.""" 44 | self.mem.flush() 45 | self.c.send_msg({"method": "blitBuffer", "params": {"bid": self.bid}}) 46 | -------------------------------------------------------------------------------- /src/termuxgui/oo/activity.py: -------------------------------------------------------------------------------- 1 | from typing import Optional 2 | 3 | import termuxgui as tg 4 | 5 | from abc import ABC 6 | from enum import Enum 7 | 8 | 9 | class Activity(tg.Activity, ABC): 10 | """Abstract base class for Activities.""" 11 | 12 | class Type(Enum): 13 | NORMAL = 1 14 | PIP = 2 15 | LOCKSCREEN = 3 16 | DIALOG = 4 17 | DIALOG_NO_CANCEL_OUTSIDE = 5 18 | 19 | def get_type(self) -> Type: 20 | """Return the type of your Activity here.""" 21 | return Activity.Type.NORMAL 22 | 23 | def intercept_back(self) -> bool: 24 | """Specify if you want to intercept back events.""" 25 | return False 26 | 27 | def __init__(self, c: tg.Connection, t: Optional[tg.Task]): 28 | args = {"intercept": self.intercept_back()} 29 | match self.get_type(): 30 | case Activity.Type.PIP: 31 | args["pip"] = True 32 | case Activity.Type.DIALOG: 33 | args["dialog"] = True 34 | case Activity.Type.DIALOG_NO_CANCEL_OUTSIDE: 35 | args["dialog"] = True 36 | args["canceloutside"] = False 37 | if t is not None: 38 | args["tid"] = t.tid 39 | tg.Activity.__init__(self, c, **args) 40 | self.root = None 41 | 42 | def on_create(self): 43 | pass 44 | 45 | def on_start(self): 46 | pass 47 | 48 | def on_resume(self): 49 | pass 50 | 51 | def on_pause(self, finishing: bool): 52 | pass 53 | 54 | def on_stop(self, finishing: bool): 55 | pass 56 | 57 | def on_destroy(self, finishing: bool): 58 | pass 59 | 60 | def on_back(self): 61 | pass 62 | 63 | def on_userleavehint(self): 64 | pass 65 | 66 | def on_pipchanged(self, pip: bool): 67 | pass 68 | 69 | def on_config(self, config: tg.activity.Configuration): 70 | pass 71 | -------------------------------------------------------------------------------- /tutorial/swiperefresh.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | 3 | import termuxgui as tg 4 | import sys 5 | 6 | with tg.Connection() as c: 7 | a = tg.Activity(c) 8 | 9 | # Intercept the back button. Instead of finishing the Activity, it now sends an event instead 10 | a.interceptbackbutton(True) 11 | # Also possible: a = tg.Activity(c, intercept=True) 12 | 13 | # Create a SwipeRefreshLayout as the root View 14 | ref = tg.SwipeRefreshLayout(a) 15 | 16 | # Add a LinearLayout as a child. A SwipeRefreshLayout can only have one child, so you should use a layout. 17 | layout = tg.LinearLayout(a, ref) 18 | 19 | refreshes = 0 20 | clicks = 0 21 | longclicks = 0 22 | 23 | tv1 = tg.TextView(a, "Refresh: " + str(refreshes), layout) 24 | tv2 = tg.TextView(a, "Clicks: " + str(clicks), layout) 25 | tv3 = tg.TextView(a, "Long clicks: " + str(longclicks), layout) 26 | 27 | # You can make other Views than Buttons send click events 28 | tv2.sendclickevent(True) 29 | 30 | # A long click event happens when you click a View and hold for a while 31 | tv3.sendlongclickevent(True) 32 | 33 | for ev in c.events(): 34 | if ev.type == tg.Event.destroy and ev.value["finishing"]: 35 | sys.exit() 36 | if ev.type == tg.Event.click: 37 | clicks += 1 38 | tv2.settext("Clicks: " + str(clicks)) 39 | if ev.type == tg.Event.longClick: 40 | longclicks += 1 41 | tv3.settext("Long clicks: " + str(longclicks)) 42 | if ev.type == tg.Event.refresh: 43 | refreshes += 1 44 | tv1.settext("Refresh: " + str(refreshes)) 45 | # Set that we are done with refreshing, so that the animation stops and the gesture can trigger again 46 | ref.setrefreshing(False) 47 | # Back button presses generate an event now 48 | if ev.type == tg.Event.back: 49 | c.toast("User pressed the back button", True) 50 | -------------------------------------------------------------------------------- /src/termuxgui/__init__.py: -------------------------------------------------------------------------------- 1 | """This is a library for interacting with the Termux:GUI plugin from python. 2 | 3 | You don't need to include all the submodules, all needed classes are automatically included in the package scope upon 4 | importing the package. """ 5 | 6 | __all__ = ['Activity', 'Buffer', 'Button', 'Checkbox', 'CompoundButton', 'Connection', 'EditText', 'Event', 7 | 'FrameLayout', "GridLayout", 'HorizontalScrollView', 'ImageView', 'LinearLayout', 'NestedScrollView', 8 | 'Notification', 'ProgressBar', 'RadioButton', 'RadioGroup', 'RemoteViews', 'Space', 'Spinner', 9 | 'SwipeRefreshLayout', 'Switch', 'TabLayout', 'Task', 'TextView', 'ToggleButton', 'View', 'ViewGroup', 10 | 'WebView'] 11 | 12 | from termuxgui.activity import Activity 13 | from termuxgui.buffer import Buffer 14 | from termuxgui.button import Button 15 | from termuxgui.checkbox import Checkbox 16 | from termuxgui.compoundbutton import CompoundButton 17 | from termuxgui.connection import Connection 18 | from termuxgui.edittext import EditText 19 | from termuxgui.event import Event 20 | from termuxgui.framelayout import FrameLayout 21 | from termuxgui.gridlayout import GridLayout 22 | from termuxgui.horizontalscrollview import HorizontalScrollView 23 | from termuxgui.imageview import ImageView 24 | from termuxgui.linearlayout import LinearLayout 25 | from termuxgui.nestedscrollview import NestedScrollView 26 | from termuxgui.notification import Notification 27 | from termuxgui.progressbar import ProgressBar 28 | from termuxgui.radiobutton import RadioButton 29 | from termuxgui.radiogroup import RadioGroup 30 | from termuxgui.remoteviews import RemoteViews 31 | from termuxgui.space import Space 32 | from termuxgui.spinner import Spinner 33 | from termuxgui.swiperefreshlayout import SwipeRefreshLayout 34 | from termuxgui.switch import Switch 35 | from termuxgui.tablayout import TabLayout 36 | from termuxgui.task import Task 37 | from termuxgui.textview import TextView 38 | from termuxgui.togglebutton import ToggleButton 39 | from termuxgui.view import View 40 | from termuxgui.viewgroup import ViewGroup 41 | from termuxgui.webview import WebView 42 | 43 | -------------------------------------------------------------------------------- /src/termuxgui/event.py: -------------------------------------------------------------------------------- 1 | class Event: 2 | """This represents an Event in the GUI. 3 | 4 | The class variables are the available event types. 5 | 6 | Use ev.type == Event.eventtype to check for event types. 7 | 8 | ev.type contains the event type and ev.value is a dictionary containing the values of the event, if any.""" 9 | 10 | # Event types 11 | # View events 12 | click = "click" 13 | longClick = "longClick" 14 | focusChange = "focusChange" 15 | key = "key" 16 | touch = "touch" 17 | refresh = "refresh" 18 | selected = "selected" # used for RadioGroups 19 | itemselected = "itemselected" 20 | text = "text" 21 | notification = "notification" 22 | notificationDismissed = "notificationDismissed" 23 | notificationaction = "notificationaction" 24 | webviewNavigation = "webviewNavigation" 25 | webviewHTTPError = "webviewHTTPError" 26 | webviewError = "webviewError" 27 | webviewDestroyed = "webviewDestroyed" 28 | webviewProgress = "webviewProgress" 29 | webviewConsoleMessage = "webviewConsoleMessage" 30 | remoteclick = "remoteclick" 31 | 32 | # activity events 33 | create = "create" 34 | start = "start" 35 | resume = "resume" 36 | pause = "pause" 37 | stop = "stop" 38 | destroy = "destroy" 39 | userleavehint = "UserLeaveHint" 40 | pipchanged = "pipchanged" 41 | config = "config" 42 | back = "back" 43 | 44 | # general events 45 | screenon = "screen_on" 46 | screen_off = "screen_off" 47 | timezone = "timezone" 48 | locale = "locale" 49 | airplane = "airplane" 50 | 51 | # special overlay events 52 | overlaytouch = "overlayTouch" 53 | overlayScale = "overlayScale" 54 | 55 | # touch event action 56 | touch_up = "up" 57 | touch_down = "down" 58 | touch_pointer_up = "pointer_up" 59 | touch_pointer_down = "pointer_down" 60 | touch_cancel = "cancel" 61 | touch_move = "move" 62 | 63 | def __init__(self, ev: dict): 64 | self.type = ev["type"] 65 | self.value = {} 66 | try: 67 | self.value = ev["value"] 68 | if type(self.value) is dict: 69 | self.aid = self.value["aid"] 70 | self.id = self.value["id"] 71 | except KeyError: 72 | pass 73 | -------------------------------------------------------------------------------- /tutorial/inputs2.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | 3 | import termuxgui as tg 4 | import sys 5 | 6 | with tg.Connection() as c: 7 | a = tg.Activity(c, dialog=True) 8 | 9 | layout = tg.LinearLayout(a) 10 | 11 | title = tg.TextView(a, "Input Demo", layout) 12 | title.settextsize(30) 13 | title.setmargin(5) 14 | 15 | # Switches have a text displayed on the left and a switch that can be set on the right 16 | switch = tg.Switch(a, "Switch", layout) 17 | 18 | # ToggleButtons are more like Buttons, but have an on/off state, but you can't set the text 19 | tb = tg.ToggleButton(a, layout) 20 | 21 | # RadioGoups are containers for RadioButtons. 22 | # Inside a RadioGroup, only one RadioButton can be set. 23 | rg = tg.RadioGroup(a, layout) 24 | 25 | # The RadioButtons are created in a list, so you can check which of them is checked more easily 26 | rbs = [tg.RadioButton(a, "Radio 1", rg), tg.RadioButton(a, "Radio 2", rg), tg.RadioButton(a, "Radio 3", rg)] 27 | 28 | # Spinners display a drop-down menu with strings to choose from 29 | spinner = tg.Spinner(a, layout) 30 | 31 | strings = ["Option 1", "Option 2", "Option 3"] 32 | 33 | # You can set the list of values to choose from 34 | spinner.setlist(strings) 35 | 36 | for ev in c.events(): 37 | if ev.type == tg.Event.destroy and ev.value["finishing"]: 38 | sys.exit() 39 | # Checked events work the same for Switches, ToggleButtons and Checkboxes 40 | if ev.type == tg.Event.click and ev.value["id"] == switch: 41 | print("Switch checked: ", ev.value["set"]) 42 | if ev.type == tg.Event.click and ev.value["id"] == tb: 43 | print("ToggleButton checked: ", ev.value["set"]) 44 | # A RadioGroup emits a selected event when a RadioButton is selected 45 | if ev.type == tg.Event.selected and ev.value["id"] == rg: 46 | # We can now use the index method of the list to find out which RadioButton is checked 47 | print("RadioButton checked: ", rbs.index(ev.value["selected"])) 48 | # Spinners emit an itemselected event 49 | if ev.type == tg.Event.itemselected and ev.value["id"] == spinner: 50 | # for itemselected events, selected is the selected value as a string 51 | print("Spinner selected: ", ev.value["selected"]) 52 | -------------------------------------------------------------------------------- /src/termuxgui/textview.py: -------------------------------------------------------------------------------- 1 | from typing import Optional, Literal 2 | 3 | from termuxgui.activity import Activity 4 | from termuxgui.view import View 5 | 6 | 7 | class TextView(View): 8 | """This represents a TextView.""" 9 | 10 | def __init__(self, activity: Activity, text: str, parent: Optional[View] = None, selectabletext: bool = False, 11 | clickablelinks: bool = False, visibility: Optional[Literal[0, 1, 2]] = None): 12 | args = {"aid": activity.aid, "text": text, "selectableText": selectabletext, "clickableLinks": clickablelinks, 13 | "visibility": visibility} 14 | if parent is not None: 15 | args["parent"] = parent.id 16 | View.__init__(self, activity, activity.c.send_read_msg({"method": "createTextView", "params": args})) 17 | 18 | def settextsize(self, size: int): 19 | """Sets the text size for this TextView.""" 20 | self.a.c.send_msg({"method": "setTextSize", "params": {"aid": self.a.aid, "id": self.id, "size": size}}) 21 | 22 | def gettext(self) -> str: 23 | """Gets the text of this TextView.""" 24 | return self.a.c.send_read_msg({"method": "getText", "params": {"aid": self.a.aid, "id": self.id}}) 25 | 26 | def settext(self, text: str): 27 | """Sets the text of this TextView.""" 28 | self.a.c.send_msg({"method": "setText", "params": {"aid": self.a.aid, "id": self.id, "text": text}}) 29 | 30 | def settextcolor(self, color: int): 31 | """Sets the text color of this TextView. The color format is the same as for Activity.settheme().""" 32 | self.a.c.send_msg({"method": "setTextColor", "params": {"aid": self.a.aid, "id": self.id, "color": color}}) 33 | 34 | def sendtextevent(self, send: bool): 35 | """Sets whether ot not text events are send for this TextView.""" 36 | self.a.c.send_msg({"method": "sendTextEvent", "params": {"aid": self.a.aid, "id": self.id, "send": send}}) 37 | 38 | def setgravity(self, horizontal: Literal[0, 1, 2], vertical: Literal[0, 1, 2]): 39 | """Sets the text gravity for this TextView. 40 | The values are: 0: left/top, 1: center, 2: right/bottom. 41 | Right and left are inverted for right-to-left layouts.""" 42 | self.a.c.send_msg({"method": "setGravity", "params": {"aid": self.a.aid, "id": self.id, 43 | "horizontal": horizontal, "vertical": vertical}}) 44 | -------------------------------------------------------------------------------- /tutorial/inputs.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | 3 | import termuxgui as tg 4 | import sys 5 | from subprocess import run 6 | 7 | with tg.Connection() as c: 8 | a = tg.Activity(c, dialog=True) # make this activity a dialog 9 | 10 | layout = tg.LinearLayout(a) 11 | 12 | title = tg.TextView(a, "Download Video", layout) 13 | title.settextsize(30) 14 | 15 | # Let's also create a small margin around the title so it looks nicer. 16 | title.setmargin(5) 17 | 18 | # For dialogs, we don't need to set "WRAP_CONTENT", in dialogs views are automatically packed as close as possible. 19 | 20 | tv1 = tg.TextView(a, "Video link:", layout) 21 | et1 = tg.EditText(a, "", layout) 22 | 23 | tv2 = tg.TextView(a, "Filename (empty for automatic filename):", layout) 24 | et2 = tg.EditText(a, "", layout) 25 | 26 | # This creates an unchecked Checkbox 27 | check = tg.Checkbox(a, "high quality", layout, False) 28 | 29 | # Create 2 buttons next to each other 30 | buttons = tg.LinearLayout(a, layout, False) 31 | 32 | dl = tg.Button(a, "download", buttons) 33 | cancel = tg.Button(a, "cancel", buttons) 34 | 35 | hd = False 36 | 37 | for ev in c.events(): 38 | if ev.type == tg.Event.destroy and ev.value["finishing"]: 39 | sys.exit() 40 | # Checkboxes also emit a click event when clicked, but they have the extra value "set" indicating whether the box is now checked or unchecked. 41 | # The id of the event is the View id. Comparing View object with view ids is supported and works as expected. 42 | if ev.type == tg.Event.click and ev.value["id"] == check: 43 | hd = ev.value["set"] 44 | if ev.type == tg.Event.click and ev.value["id"] == dl: 45 | link = et1.gettext() 46 | name = et2.gettext() 47 | args = ["youtubedr", "download"] 48 | if len(name) != 0: 49 | args.extend(["-o", name]) 50 | if hd: 51 | args.extend(["-q", "1080p"]) 52 | args.append(link) 53 | if len(link) != 0: 54 | try: 55 | a.finish() 56 | run(args) 57 | except: 58 | pass 59 | if ev.type == tg.Event.click and ev.value["id"] == cancel: 60 | a.finish() # this handily also exits the program, because finishing the activity destroys it, and that event is send to us 61 | -------------------------------------------------------------------------------- /tutorial/helloevents.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | 3 | import termuxgui as tg 4 | import time 5 | import threading 6 | 7 | with tg.Connection() as c: 8 | a = tg.Activity(c) 9 | 10 | # For each View or Layout you create you can specify the parent Layout to create a hierarchy. 11 | # If you don't specify a parent, it will replace the current root View. 12 | # We first create a LinearLayout as our root View. 13 | root = tg.LinearLayout(a) 14 | 15 | # Then we create a TextView that we will use as a title 16 | title = tg.TextView(a, "Awesome Title", root) 17 | 18 | # We set the font size a bit bigger 19 | title.settextsize(30) 20 | 21 | contenttext = "Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod " \ 22 | "tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At " \ 23 | "vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, " \ 24 | "no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit " \ 25 | "amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut " \ 26 | "labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam " \ 27 | "et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata " \ 28 | "sanctus est Lorem ipsum dolor sit amet." 29 | # Now we create a TextView for the main content 30 | content = tg.TextView(a, contenttext, root) 31 | 32 | # And we add a Button at the end 33 | button = tg.Button(a, "Click here!", root) 34 | 35 | # Now we give the layout priority to our content Textview so it is bigger than the Button and the title. 36 | content.setlinearlayoutparams(10) 37 | 38 | count = 0 39 | 40 | # create a thread to handle the events, so we can still exit the program after 5 seconds no matter what 41 | def handleEvents(): 42 | global count 43 | for ev in c.events(): # waits for events from the gui 44 | # checks for click events. We don't need to check the id, as there is only one Button in our example 45 | if ev.type == tg.Event.click: 46 | count = count + 1 47 | 48 | 49 | watcher = threading.Thread(target=handleEvents, daemon=True) 50 | watcher.start() 51 | 52 | time.sleep(5) 53 | print("button pressed", count, "times") 54 | -------------------------------------------------------------------------------- /TUTORIAL_OOP.md: -------------------------------------------------------------------------------- 1 | # Python Bindings OOP Tutorial 2 | 3 | This is the tutorial for the object-oriented version of this library. 4 | Make sure you're familiar with the normal version a bit first, many things aren't explicitly repeated here. 5 | 6 | Make sure you installed the library like explained in the README. 7 | This tutorial assumes you have the basic understanding of the Android GUI from the [crash course](https://github.com/termux/termux-gui). 8 | The full source code can also be found in the tutorial_oop folder. 9 | 10 | ## Basic structure 11 | 12 | Activities are now defined as classes, Layouts can be defined as classes for reusability, 13 | the event loop is now build into the connection and with it comes an event system. 14 | You can also override the on_* methods of your Activity to catch Activity events. 15 | 16 | 17 | 18 | 19 | 20 | ```python 21 | # Some classes like RemoteViews and Buffer are still required from termuxgui, so import both 22 | import termuxgui.oo as tgo 23 | import termuxgui as tg 24 | 25 | 26 | # Layouts can be defined as classes, to make them reusable 27 | class HelloWorldLayout(tgo.LinearLayout): 28 | def __init__(self, activity: tgo.Activity): 29 | # Initialize the LinearLayout as the root Layout 30 | super().__init__(activity) 31 | # define a TextView 32 | tgo.TextView(self.a, "Hello World", self) 33 | # define a Button 34 | b = tgo.Button(self.a, "Click me!", self) 35 | # Also new is the event system: 36 | # You can provide callables as on_* methods which will be called 37 | # if the corresponding Event is triggered on the View. 38 | # The methods get the event and the View as parameters. 39 | b.on_click = lambda e, v: print(e.type, e.value, v.id) 40 | 41 | 42 | # Activities are now classes 43 | class HelloWorldActivity(tgo.Activity): 44 | 45 | def __init__(self, c, t): 46 | super().__init__(c, t) 47 | # Add the Layout to the Activity 48 | HelloWorldLayout(self) 49 | 50 | 51 | with tgo.Connection() as c: 52 | # Activities aren't created directly with the constructor anymore, but with the launch method of the connection 53 | c.launch(HelloWorldActivity) 54 | 55 | # The event loop is build into the connection. 56 | # It automatically quits if there aren't any Activities left. 57 | c.event_loop() 58 | ``` 59 | 60 | [helloworld.py](tutorial_oop/helloworld.py) 61 | 62 | 63 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Byte-compiled / optimized / DLL files 2 | __pycache__/ 3 | *.py[cod] 4 | *$py.class 5 | 6 | # C extensions 7 | *.so 8 | 9 | # Distribution / packaging 10 | .Python 11 | build/ 12 | develop-eggs/ 13 | dist/ 14 | downloads/ 15 | eggs/ 16 | .eggs/ 17 | lib/ 18 | lib64/ 19 | parts/ 20 | sdist/ 21 | var/ 22 | wheels/ 23 | pip-wheel-metadata/ 24 | share/python-wheels/ 25 | *.egg-info/ 26 | .installed.cfg 27 | *.egg 28 | MANIFEST 29 | 30 | # PyInstaller 31 | # Usually these files are written by a python script from a template 32 | # before PyInstaller builds the exe, so as to inject date/other infos into it. 33 | *.manifest 34 | *.spec 35 | 36 | # Installer logs 37 | pip-log.txt 38 | pip-delete-this-directory.txt 39 | 40 | # Unit test / coverage reports 41 | htmlcov/ 42 | .tox/ 43 | .nox/ 44 | .coverage 45 | .coverage.* 46 | .cache 47 | nosetests.xml 48 | coverage.xml 49 | *.cover 50 | *.py,cover 51 | .hypothesis/ 52 | .pytest_cache/ 53 | 54 | # Translations 55 | *.mo 56 | *.pot 57 | 58 | # Django stuff: 59 | *.log 60 | local_settings.py 61 | db.sqlite3 62 | db.sqlite3-journal 63 | 64 | # Flask stuff: 65 | instance/ 66 | .webassets-cache 67 | 68 | # Scrapy stuff: 69 | .scrapy 70 | 71 | # Sphinx documentation 72 | docs/_build/ 73 | 74 | # PyBuilder 75 | target/ 76 | 77 | # Jupyter Notebook 78 | .ipynb_checkpoints 79 | 80 | # IPython 81 | profile_default/ 82 | ipython_config.py 83 | 84 | # pyenv 85 | .python-version 86 | 87 | # pipenv 88 | # According to pypa/pipenv#598, it is recommended to include Pipfile.lock in version control. 89 | # However, in case of collaboration, if having platform-specific dependencies or dependencies 90 | # having no cross-platform support, pipenv may install dependencies that don't work, or not 91 | # install all needed dependencies. 92 | #Pipfile.lock 93 | 94 | # PEP 582; used by e.g. github.com/David-OConnor/pyflow 95 | __pypackages__/ 96 | 97 | # Celery stuff 98 | celerybeat-schedule 99 | celerybeat.pid 100 | 101 | # SageMath parsed files 102 | *.sage.py 103 | 104 | # Environments 105 | .env 106 | .venv 107 | env/ 108 | venv/ 109 | ENV/ 110 | env.bak/ 111 | venv.bak/ 112 | 113 | # Spyder project settings 114 | .spyderproject 115 | .spyproject 116 | 117 | # Rope project settings 118 | .ropeproject 119 | 120 | # mkdocs documentation 121 | /site 122 | 123 | # mypy 124 | .mypy_cache/ 125 | .dmypy.json 126 | dmypy.json 127 | 128 | # Pyre type checker 129 | .pyre/ 130 | 131 | # IntelliJ 132 | /.idea -------------------------------------------------------------------------------- /src/termuxgui/webview.py: -------------------------------------------------------------------------------- 1 | from typing import Optional, Literal 2 | 3 | from termuxgui.activity import Activity 4 | from termuxgui.view import View 5 | 6 | 7 | class WebView(View): 8 | """This represents a WebView.""" 9 | 10 | def __init__(self, activity: Activity, parent: Optional[View] = None, 11 | visibility: Optional[Literal[0, 1, 2]] = None): 12 | args = {"aid": activity.aid, "visibility": visibility} 13 | if parent is not None: 14 | args["parent"] = parent.id 15 | View.__init__(self, activity, activity.c.send_read_msg({"method": "createWebView", "params": args})) 16 | 17 | def allowjavascript(self, allow: bool): 18 | """Sets whether Javascript execution is allowed in the WebView. 19 | If requesting to allow, the user is prompted and can deny the request. 20 | Blocks until the user responded. 21 | Returns wheter Javascript is enabled after the call.""" 22 | self.a.c.send_read_msg({"method": "allowJavascript", "params": {"aid": self.a.aid, "id": self.id, "allow": allow}}) 23 | 24 | def allowcontenturi(self, allow: bool): 25 | """Sets whether it is allowed to load content from a content:// URI.""" 26 | self.a.c.send_msg({"method": "allowContentURI", "params": {"aid": self.a.aid, "id": self.id, "allow": allow}}) 27 | 28 | def allownavigation(self, allow: bool): 29 | """Sets whether the user and Javascript are allowed to navigate to different sites.""" 30 | self.a.c.send_msg({"method": "allowNavigation", "params": {"aid": self.a.aid, "id": self.id, "allow": allow}}) 31 | 32 | def setdata(self, data: str): 33 | """Sets the document data.""" 34 | self.a.c.send_msg({"method": "setData", "params": {"aid": self.a.aid, "id": self.id, "doc": data}}) 35 | 36 | def loaduri(self, uri: str): 37 | """Loads a URI.""" 38 | self.a.c.send_msg({"method": "loadURI", "params": {"aid": self.a.aid, "id": self.id, "uri": uri}}) 39 | 40 | def goback(self): 41 | """Goes back in the history.""" 42 | self.a.c.send_msg({"method": "goBack", "params": {"aid": self.a.aid, "id": self.id}}) 43 | 44 | def goforward(self): 45 | """Goes forward in the history.""" 46 | self.a.c.send_msg({"method": "goForward", "params": {"aid": self.a.aid, "id": self.id}}) 47 | 48 | def evaluatejs(self, code: str): 49 | """Runs Javascript in the WebView, if Javascript is enabled.""" 50 | self.a.c.send_msg({"method": "evaluateJS", "params": {"aid": self.a.aid, "id": self.id, "code": code}}) 51 | -------------------------------------------------------------------------------- /tutorial/pagedlist.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | 3 | import termuxgui as tg 4 | import sys 5 | 6 | with tg.Connection() as c: 7 | a = tg.Activity(c) 8 | 9 | # set the amount of items on each page 10 | pagesize = 20 11 | 12 | # generate content 13 | pagedcontent = [] 14 | for i in range(1, 201): 15 | pagedcontent.append(f'Item {i}') 16 | 17 | page = 0 18 | 19 | # the paged list will be contained in this layout, and can be placed anywhere in the layout 20 | pagedlayout = tg.LinearLayout(a) 21 | 22 | # construct the controls at the top 23 | pagedcontrols = tg.LinearLayout(a, pagedlayout, vertical=False) 24 | pagedcontrols.setlinearlayoutparams(0) 25 | pagedcontrols.setheight(tg.View.WRAP_CONTENT) 26 | 27 | # buttons to go forward and back, and a display 28 | pagedback = tg.Button(a, "-", pagedcontrols) 29 | pagedpageview = tg.TextView(a, "1/1", pagedcontrols) 30 | pagedforward = tg.Button(a, "+", pagedcontrols) 31 | 32 | pagedback.setwidth(tg.View.WRAP_CONTENT) 33 | pagedforward.setwidth(tg.View.WRAP_CONTENT) 34 | 35 | pagedpageview.setmargin(5, "left") 36 | pagedpageview.setmargin(5, "right") 37 | pagedpageview.setgravity(1, 1) # Center the text 38 | 39 | # make the NestedScrollView for the content 40 | pagedscrollview = tg.NestedScrollView(a, pagedlayout) 41 | pagedscrollviewlayout = tg.LinearLayout(a, pagedscrollview) 42 | 43 | # Generate the Views for the content ahead of time, so the transition between pages 44 | # takes less time, and the user doesn't see a black flicker while the Views are removed 45 | pagedviews = [] 46 | for i in range(0, pagesize): 47 | pagedviews.append(tg.TextView(a, "", pagedscrollviewlayout)) 48 | pagedviews[i].settextsize(25) 49 | 50 | def topage(p: int): 51 | global page 52 | page = p 53 | # update the page indicator 54 | pagedpageview.settext(f"{p+1}/{int(len(pagedcontent)/pagesize)}") 55 | # set the new content 56 | for i in range(0, pagesize): 57 | pagedviews[i].settext(pagedcontent[p*pagesize+i]) 58 | 59 | topage(0) 60 | 61 | for ev in c.events(): 62 | if ev.type == tg.Event.destroy and ev.value["finishing"]: 63 | sys.exit() 64 | if ev.type == tg.Event.click: 65 | if ev.value["id"] == pagedback and page > 0: 66 | topage(page-1) 67 | if ev.value["id"] == pagedforward and page < (len(pagedcontent)/pagesize)-1: 68 | topage(page+1) 69 | -------------------------------------------------------------------------------- /tutorial/pages.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | 3 | import sys 4 | import termuxgui as tg 5 | import time 6 | import threading 7 | 8 | with tg.Connection() as c: 9 | a = tg.Activity(c) 10 | 11 | root = tg.LinearLayout(a) 12 | 13 | # Create the TabLayout first, so it's at the top 14 | tabs = tg.TabLayout(a, root) 15 | 16 | # Set the tabs 17 | tabs.setlist(["Page 1", "Page 2", "Page 3"]) 18 | 19 | tabs.setlinearlayoutparams(0) 20 | tabs.setheight(tg.View.WRAP_CONTENT) 21 | 22 | # Create a HorizontalScrollView without a visible scrollbar that snaps to the nearest item 23 | sv = tg.HorizontalScrollView(a, root, fillviewport=True, snapping=True, nobar=True) 24 | 25 | # wait until the activity is displayed and teh size is known 26 | while sv.getdimensions()[0] == 0: 27 | time.sleep(0.001) 28 | 29 | # Get the width one page should have 30 | pagew = sv.getdimensions()[0] 31 | 32 | # Create a horizontal layout 33 | svl = tg.LinearLayout(a, sv, vertical=False) 34 | 35 | # Create 3 pages 36 | page1 = tg.TextView(a, "Page 1", svl) 37 | page2 = tg.TextView(a, "Page 2", svl) 38 | page3 = tg.TextView(a, "Page 3", svl) 39 | 40 | # Set the width to one page-width 41 | page1.setwidth(pagew, True) 42 | page2.setwidth(pagew, True) 43 | page3.setwidth(pagew, True) 44 | 45 | # access to the gui objects has to be synchronized between threads 46 | conlcok = threading.Lock() 47 | 48 | tabselected = False 49 | tab = 0 50 | 51 | # create a thread to watch the scroll position and select the tab accordingly 52 | def watchscrollview(): 53 | global tabselected 54 | while True: 55 | with conlcok: 56 | p = round(sv.getscrollposition()[0]/pagew) 57 | if not tabselected: 58 | if p != tab: 59 | tabs.selecttab(p) 60 | tabselected = True 61 | elif p == tab: 62 | tabselected = False 63 | time.sleep(0.01) 64 | threading.Thread(target=watchscrollview, daemon=True).start() 65 | 66 | # getting events needs no synchronisation... 67 | for ev in c.events(): 68 | if ev.type == tg.Event.destroy: 69 | sys.exit() 70 | # TabLayout also emits an itemselected event, but has the tab index as the value 71 | if ev.type == tg.Event.itemselected and ev.value["id"] == tabs: 72 | # ...but calling any other method does 73 | with conlcok: 74 | tabselected = True 75 | tab = ev.value["selected"] 76 | # Scroll to the selected tab 77 | sv.setscrollposition(pagew*tab, 0, True) 78 | -------------------------------------------------------------------------------- /tutorial/buffers.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | 3 | import time 4 | from ctypes import * 5 | from sdl2 import * 6 | import sdl2.ext 7 | import gc 8 | 9 | import termuxgui as tg 10 | 11 | with tg.Connection() as c: 12 | a = tg.Activity(c) 13 | time.sleep(0.5) # wait for the activity to show 14 | 15 | im = tg.ImageView(a) 16 | 17 | # This create a pixel buffer with size 500x500 18 | b = tg.Buffer(c, 500, 500) 19 | 20 | # This sets the ImageView to display the buffer 21 | im.setbuffer(b) 22 | 23 | with b as mem: 24 | # This creates a c void pointer from the shared memory 25 | memp = cast(pointer(c_uint8.from_buffer(mem, 0)), c_void_p) 26 | 27 | # We initialize the video system of SDL 28 | SDL_Init(SDL_INIT_VIDEO) 29 | 30 | # Then we create a SDL surface from our buffer. We pass in the pointer to our buffer, the buffer width and 31 | # height, the bit depth (the format is always ARGB8888, so it's 32 bits), wthe pitch (bytes per row), 32 | # and the masks for the color values. The mask determines the format and is the same for all buffers 33 | surf = SDL_CreateRGBSurfaceFrom(memp, 500, 500, 32, 4 * 500, c_uint(0xff), c_uint(0xff00), c_uint(0xff0000), 34 | c_uint(0xff000000)) 35 | 36 | # in general you would write: 37 | # SDL_CreateRGBSurfaceFrom(memp, width, height, 32, 4*width, c_uint(0xff), c_uint(0xff00), c_uint(0xff0000), c_uint(0xff000000)) 38 | 39 | white = sdl2.ext.Color(255, 255, 255, 255) # Color in RGBA format 40 | red = sdl2.ext.Color(255, 0, 0, 255) 41 | green = sdl2.ext.Color(0, 255, 0, 255) 42 | blue = sdl2.ext.Color(0, 0, 255, 255) 43 | 44 | for i in range(490): 45 | # clear the buffer 46 | sdl2.ext.fill(surf, white) 47 | 48 | # make a red square go from the top left to the bottom right 49 | sdl2.ext.fill(surf, red, (i, i, 10, 10)) 50 | 51 | # make a green square go from the top right to the bottom left 52 | sdl2.ext.fill(surf, green, (490 - i, i, 10, 10)) 53 | 54 | # make a blue square go from the top middle to the bottom middle 55 | sdl2.ext.fill(surf, blue, (245, i, 10, 10)) 56 | 57 | # blit the shared memory buffer 58 | b.blit() 59 | # now we have to request that the ImageView redraws itself to reflect the new contents of the buffer 60 | im.refresh() 61 | 62 | time.sleep(0.01) 63 | 64 | # Make sure the shared memory can be closed 65 | del memp # free the pointer 66 | gc.collect() # let the garbage collector run, so the pointer is really discarded 67 | 68 | # do proper cleanup of SDL 69 | SDL_FreeSurface(surf) 70 | SDL_Quit() 71 | 72 | time.sleep(0.2) 73 | -------------------------------------------------------------------------------- /src/termuxgui/oo/connection.py: -------------------------------------------------------------------------------- 1 | from typing import Type, Optional 2 | 3 | import termuxgui as tg 4 | from termuxgui.oo.activity import Activity 5 | from termuxgui.oo.view import View 6 | 7 | 8 | def _dispatch_event_recursive(e: tg.Event, v: View) -> bool: 9 | if v.id == e.id: 10 | if hasattr(v, "on_"+e.type): 11 | getattr(v, "on_"+e.type)(e, v) 12 | return True 13 | if hasattr(v, "views"): 14 | views = getattr(v, "views") 15 | for child in views: 16 | ret = _dispatch_event_recursive(e, child) 17 | if ret: 18 | return True 19 | return False 20 | 21 | 22 | class Connection(tg.Connection): 23 | """This represents a connection to the Termux:GUI plugin and contains all functions that don't act on any 24 | particular View, Activity or Task. """ 25 | 26 | __activities: dict[str, Activity] = {} 27 | 28 | """Launches an Activity with the specified parameters.""" 29 | def launch(self, activity: Type[Activity], t: Optional[tg.Task] = None, *args, **kwargs): 30 | a = activity(self, t, *args, *kwargs) 31 | self.__activities[a.aid] = a 32 | 33 | """Runs the event loop. Dispatches events to Activities and Views. Exits if there aren't any Activities anymore.""" 34 | def event_loop(self): 35 | for e in self.events(): 36 | if hasattr(e, "aid"): 37 | a = self.__activities[e.aid] 38 | if a is not None: 39 | match [e.type]: 40 | case [tg.Event.create]: 41 | a.on_create() 42 | case [tg.Event.start]: 43 | a.on_start() 44 | case [tg.Event.resume]: 45 | a.on_resume() 46 | case [tg.Event.pause]: 47 | a.on_pause(e.value["finishing"]) 48 | case [tg.Event.stop]: 49 | a.on_stop(e.value["finishing"]) 50 | case [tg.Event.destroy]: 51 | a.on_destroy(e.value["finishing"]) 52 | del self.__activities[e.aid] 53 | case [tg.Event.back]: 54 | a.on_back() 55 | case [tg.Event.userleavehint]: 56 | a.on_userleavehint() 57 | case [tg.Event.pipchanged]: 58 | a.on_pipchanged(e.value) 59 | case [tg.Event.config]: 60 | a.on_config(e.value) 61 | case [tg.Event.click | tg.Event.longClick | tg.Event.focusChange | tg.Event.key | 62 | tg.Event.touch | tg.Event.refresh | tg.Event.selected | tg.Event.itemselected | 63 | tg.Event.text | tg.Event.webviewNavigation | tg.Event.webviewHTTPError | 64 | tg.Event.webviewError | tg.Event.webviewDestroyed | tg.Event.webviewProgress | 65 | tg.Event.webviewConsoleMessage]: 66 | if a.root is not None: 67 | _dispatch_event_recursive(e, a.root) 68 | case _: 69 | pass 70 | if len(self.__activities) == 0: 71 | return 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | -------------------------------------------------------------------------------- /docs/search.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 |57 | Searching for multiple words only shows matches that contain 58 | all words. 59 |
60 | 61 | 62 | 67 | 68 | 69 | 70 || 51 | t | ||
| 55 | |
56 | termuxgui | 57 | |
| 60 | |
61 | termuxgui.oo | 62 | |
Contents:
47 |' + 152 | '' + 153 | Documentation.gettext("Hide Search Matches") + 154 | "
" 155 | ) 156 | ); 157 | }, 158 | 159 | /** 160 | * helper function to hide the search marks again 161 | */ 162 | hideSearchWords: () => { 163 | document 164 | .querySelectorAll("#searchbox .highlight-link") 165 | .forEach((el) => el.remove()); 166 | document 167 | .querySelectorAll("span.highlighted") 168 | .forEach((el) => el.classList.remove("highlighted")); 169 | const url = new URL(window.location); 170 | url.searchParams.delete("highlight"); 171 | window.history.replaceState({}, "", url); 172 | }, 173 | 174 | /** 175 | * helper function to focus on search bar 176 | */ 177 | focusSearchBar: () => { 178 | document.querySelectorAll("input[name=q]")[0]?.focus(); 179 | }, 180 | 181 | /** 182 | * Initialise the domain index toggle buttons 183 | */ 184 | initDomainIndexTable: () => { 185 | const toggler = (el) => { 186 | const idNumber = el.id.substr(7); 187 | const toggledRows = document.querySelectorAll(`tr.cg-${idNumber}`); 188 | if (el.src.substr(-9) === "minus.png") { 189 | el.src = `${el.src.substr(0, el.src.length - 9)}plus.png`; 190 | toggledRows.forEach((el) => (el.style.display = "none")); 191 | } else { 192 | el.src = `${el.src.substr(0, el.src.length - 8)}minus.png`; 193 | toggledRows.forEach((el) => (el.style.display = "")); 194 | } 195 | }; 196 | 197 | const togglerElements = document.querySelectorAll("img.toggler"); 198 | togglerElements.forEach((el) => 199 | el.addEventListener("click", (event) => toggler(event.currentTarget)) 200 | ); 201 | togglerElements.forEach((el) => (el.style.display = "")); 202 | if (DOCUMENTATION_OPTIONS.COLLAPSE_INDEX) togglerElements.forEach(toggler); 203 | }, 204 | 205 | initOnKeyListeners: () => { 206 | // only install a listener if it is really needed 207 | if ( 208 | !DOCUMENTATION_OPTIONS.NAVIGATION_WITH_KEYS && 209 | !DOCUMENTATION_OPTIONS.ENABLE_SEARCH_SHORTCUTS 210 | ) 211 | return; 212 | 213 | const blacklistedElements = new Set([ 214 | "TEXTAREA", 215 | "INPUT", 216 | "SELECT", 217 | "BUTTON", 218 | ]); 219 | document.addEventListener("keydown", (event) => { 220 | if (blacklistedElements.has(document.activeElement.tagName)) return; // bail for input elements 221 | if (event.altKey || event.ctrlKey || event.metaKey) return; // bail with special keys 222 | 223 | if (!event.shiftKey) { 224 | switch (event.key) { 225 | case "ArrowLeft": 226 | if (!DOCUMENTATION_OPTIONS.NAVIGATION_WITH_KEYS) break; 227 | 228 | const prevLink = document.querySelector('link[rel="prev"]'); 229 | if (prevLink && prevLink.href) { 230 | window.location.href = prevLink.href; 231 | event.preventDefault(); 232 | } 233 | break; 234 | case "ArrowRight": 235 | if (!DOCUMENTATION_OPTIONS.NAVIGATION_WITH_KEYS) break; 236 | 237 | const nextLink = document.querySelector('link[rel="next"]'); 238 | if (nextLink && nextLink.href) { 239 | window.location.href = nextLink.href; 240 | event.preventDefault(); 241 | } 242 | break; 243 | case "Escape": 244 | if (!DOCUMENTATION_OPTIONS.ENABLE_SEARCH_SHORTCUTS) break; 245 | Documentation.hideSearchWords(); 246 | event.preventDefault(); 247 | } 248 | } 249 | 250 | // some keyboard layouts may need Shift to get / 251 | switch (event.key) { 252 | case "/": 253 | if (!DOCUMENTATION_OPTIONS.ENABLE_SEARCH_SHORTCUTS) break; 254 | Documentation.focusSearchBar(); 255 | event.preventDefault(); 256 | } 257 | }); 258 | }, 259 | }; 260 | 261 | // quick alias for translations 262 | const _ = Documentation.gettext; 263 | 264 | _ready(Documentation.init); 265 | -------------------------------------------------------------------------------- /docs/_static/alabaster.css: -------------------------------------------------------------------------------- 1 | @import url("basic.css"); 2 | 3 | /* -- page layout ----------------------------------------------------------- */ 4 | 5 | body { 6 | font-family: Georgia, serif; 7 | font-size: 17px; 8 | background-color: #fff; 9 | color: #000; 10 | margin: 0; 11 | padding: 0; 12 | } 13 | 14 | 15 | div.document { 16 | width: 940px; 17 | margin: 30px auto 0 auto; 18 | } 19 | 20 | div.documentwrapper { 21 | float: left; 22 | width: 100%; 23 | } 24 | 25 | div.bodywrapper { 26 | margin: 0 0 0 220px; 27 | } 28 | 29 | div.sphinxsidebar { 30 | width: 220px; 31 | font-size: 14px; 32 | line-height: 1.5; 33 | } 34 | 35 | hr { 36 | border: 1px solid #B1B4B6; 37 | } 38 | 39 | div.body { 40 | background-color: #fff; 41 | color: #3E4349; 42 | padding: 0 30px 0 30px; 43 | } 44 | 45 | div.body > .section { 46 | text-align: left; 47 | } 48 | 49 | div.footer { 50 | width: 940px; 51 | margin: 20px auto 30px auto; 52 | font-size: 14px; 53 | color: #888; 54 | text-align: right; 55 | } 56 | 57 | div.footer a { 58 | color: #888; 59 | } 60 | 61 | p.caption { 62 | font-family: inherit; 63 | font-size: inherit; 64 | } 65 | 66 | 67 | div.relations { 68 | display: none; 69 | } 70 | 71 | 72 | div.sphinxsidebar a { 73 | color: #444; 74 | text-decoration: none; 75 | border-bottom: 1px dotted #999; 76 | } 77 | 78 | div.sphinxsidebar a:hover { 79 | border-bottom: 1px solid #999; 80 | } 81 | 82 | div.sphinxsidebarwrapper { 83 | padding: 18px 10px; 84 | } 85 | 86 | div.sphinxsidebarwrapper p.logo { 87 | padding: 0; 88 | margin: -10px 0 0 0px; 89 | text-align: center; 90 | } 91 | 92 | div.sphinxsidebarwrapper h1.logo { 93 | margin-top: -10px; 94 | text-align: center; 95 | margin-bottom: 5px; 96 | text-align: left; 97 | } 98 | 99 | div.sphinxsidebarwrapper h1.logo-name { 100 | margin-top: 0px; 101 | } 102 | 103 | div.sphinxsidebarwrapper p.blurb { 104 | margin-top: 0; 105 | font-style: normal; 106 | } 107 | 108 | div.sphinxsidebar h3, 109 | div.sphinxsidebar h4 { 110 | font-family: Georgia, serif; 111 | color: #444; 112 | font-size: 24px; 113 | font-weight: normal; 114 | margin: 0 0 5px 0; 115 | padding: 0; 116 | } 117 | 118 | div.sphinxsidebar h4 { 119 | font-size: 20px; 120 | } 121 | 122 | div.sphinxsidebar h3 a { 123 | color: #444; 124 | } 125 | 126 | div.sphinxsidebar p.logo a, 127 | div.sphinxsidebar h3 a, 128 | div.sphinxsidebar p.logo a:hover, 129 | div.sphinxsidebar h3 a:hover { 130 | border: none; 131 | } 132 | 133 | div.sphinxsidebar p { 134 | color: #555; 135 | margin: 10px 0; 136 | } 137 | 138 | div.sphinxsidebar ul { 139 | margin: 10px 0; 140 | padding: 0; 141 | color: #000; 142 | } 143 | 144 | div.sphinxsidebar ul li.toctree-l1 > a { 145 | font-size: 120%; 146 | } 147 | 148 | div.sphinxsidebar ul li.toctree-l2 > a { 149 | font-size: 110%; 150 | } 151 | 152 | div.sphinxsidebar input { 153 | border: 1px solid #CCC; 154 | font-family: Georgia, serif; 155 | font-size: 1em; 156 | } 157 | 158 | div.sphinxsidebar hr { 159 | border: none; 160 | height: 1px; 161 | color: #AAA; 162 | background: #AAA; 163 | 164 | text-align: left; 165 | margin-left: 0; 166 | width: 50%; 167 | } 168 | 169 | div.sphinxsidebar .badge { 170 | border-bottom: none; 171 | } 172 | 173 | div.sphinxsidebar .badge:hover { 174 | border-bottom: none; 175 | } 176 | 177 | /* To address an issue with donation coming after search */ 178 | div.sphinxsidebar h3.donation { 179 | margin-top: 10px; 180 | } 181 | 182 | /* -- body styles ----------------------------------------------------------- */ 183 | 184 | a { 185 | color: #004B6B; 186 | text-decoration: underline; 187 | } 188 | 189 | a:hover { 190 | color: #6D4100; 191 | text-decoration: underline; 192 | } 193 | 194 | div.body h1, 195 | div.body h2, 196 | div.body h3, 197 | div.body h4, 198 | div.body h5, 199 | div.body h6 { 200 | font-family: Georgia, serif; 201 | font-weight: normal; 202 | margin: 30px 0px 10px 0px; 203 | padding: 0; 204 | } 205 | 206 | div.body h1 { margin-top: 0; padding-top: 0; font-size: 240%; } 207 | div.body h2 { font-size: 180%; } 208 | div.body h3 { font-size: 150%; } 209 | div.body h4 { font-size: 130%; } 210 | div.body h5 { font-size: 100%; } 211 | div.body h6 { font-size: 100%; } 212 | 213 | a.headerlink { 214 | color: #DDD; 215 | padding: 0 4px; 216 | text-decoration: none; 217 | } 218 | 219 | a.headerlink:hover { 220 | color: #444; 221 | background: #EAEAEA; 222 | } 223 | 224 | div.body p, div.body dd, div.body li { 225 | line-height: 1.4em; 226 | } 227 | 228 | div.admonition { 229 | margin: 20px 0px; 230 | padding: 10px 30px; 231 | background-color: #EEE; 232 | border: 1px solid #CCC; 233 | } 234 | 235 | div.admonition tt.xref, div.admonition code.xref, div.admonition a tt { 236 | background-color: #FBFBFB; 237 | border-bottom: 1px solid #fafafa; 238 | } 239 | 240 | div.admonition p.admonition-title { 241 | font-family: Georgia, serif; 242 | font-weight: normal; 243 | font-size: 24px; 244 | margin: 0 0 10px 0; 245 | padding: 0; 246 | line-height: 1; 247 | } 248 | 249 | div.admonition p.last { 250 | margin-bottom: 0; 251 | } 252 | 253 | div.highlight { 254 | background-color: #fff; 255 | } 256 | 257 | dt:target, .highlight { 258 | background: #FAF3E8; 259 | } 260 | 261 | div.warning { 262 | background-color: #FCC; 263 | border: 1px solid #FAA; 264 | } 265 | 266 | div.danger { 267 | background-color: #FCC; 268 | border: 1px solid #FAA; 269 | -moz-box-shadow: 2px 2px 4px #D52C2C; 270 | -webkit-box-shadow: 2px 2px 4px #D52C2C; 271 | box-shadow: 2px 2px 4px #D52C2C; 272 | } 273 | 274 | div.error { 275 | background-color: #FCC; 276 | border: 1px solid #FAA; 277 | -moz-box-shadow: 2px 2px 4px #D52C2C; 278 | -webkit-box-shadow: 2px 2px 4px #D52C2C; 279 | box-shadow: 2px 2px 4px #D52C2C; 280 | } 281 | 282 | div.caution { 283 | background-color: #FCC; 284 | border: 1px solid #FAA; 285 | } 286 | 287 | div.attention { 288 | background-color: #FCC; 289 | border: 1px solid #FAA; 290 | } 291 | 292 | div.important { 293 | background-color: #EEE; 294 | border: 1px solid #CCC; 295 | } 296 | 297 | div.note { 298 | background-color: #EEE; 299 | border: 1px solid #CCC; 300 | } 301 | 302 | div.tip { 303 | background-color: #EEE; 304 | border: 1px solid #CCC; 305 | } 306 | 307 | div.hint { 308 | background-color: #EEE; 309 | border: 1px solid #CCC; 310 | } 311 | 312 | div.seealso { 313 | background-color: #EEE; 314 | border: 1px solid #CCC; 315 | } 316 | 317 | div.topic { 318 | background-color: #EEE; 319 | } 320 | 321 | p.admonition-title { 322 | display: inline; 323 | } 324 | 325 | p.admonition-title:after { 326 | content: ":"; 327 | } 328 | 329 | pre, tt, code { 330 | font-family: 'Consolas', 'Menlo', 'DejaVu Sans Mono', 'Bitstream Vera Sans Mono', monospace; 331 | font-size: 0.9em; 332 | } 333 | 334 | .hll { 335 | background-color: #FFC; 336 | margin: 0 -12px; 337 | padding: 0 12px; 338 | display: block; 339 | } 340 | 341 | img.screenshot { 342 | } 343 | 344 | tt.descname, tt.descclassname, code.descname, code.descclassname { 345 | font-size: 0.95em; 346 | } 347 | 348 | tt.descname, code.descname { 349 | padding-right: 0.08em; 350 | } 351 | 352 | img.screenshot { 353 | -moz-box-shadow: 2px 2px 4px #EEE; 354 | -webkit-box-shadow: 2px 2px 4px #EEE; 355 | box-shadow: 2px 2px 4px #EEE; 356 | } 357 | 358 | table.docutils { 359 | border: 1px solid #888; 360 | -moz-box-shadow: 2px 2px 4px #EEE; 361 | -webkit-box-shadow: 2px 2px 4px #EEE; 362 | box-shadow: 2px 2px 4px #EEE; 363 | } 364 | 365 | table.docutils td, table.docutils th { 366 | border: 1px solid #888; 367 | padding: 0.25em 0.7em; 368 | } 369 | 370 | table.field-list, table.footnote { 371 | border: none; 372 | -moz-box-shadow: none; 373 | -webkit-box-shadow: none; 374 | box-shadow: none; 375 | } 376 | 377 | table.footnote { 378 | margin: 15px 0; 379 | width: 100%; 380 | border: 1px solid #EEE; 381 | background: #FDFDFD; 382 | font-size: 0.9em; 383 | } 384 | 385 | table.footnote + table.footnote { 386 | margin-top: -15px; 387 | border-top: none; 388 | } 389 | 390 | table.field-list th { 391 | padding: 0 0.8em 0 0; 392 | } 393 | 394 | table.field-list td { 395 | padding: 0; 396 | } 397 | 398 | table.field-list p { 399 | margin-bottom: 0.8em; 400 | } 401 | 402 | /* Cloned from 403 | * https://github.com/sphinx-doc/sphinx/commit/ef60dbfce09286b20b7385333d63a60321784e68 404 | */ 405 | .field-name { 406 | -moz-hyphens: manual; 407 | -ms-hyphens: manual; 408 | -webkit-hyphens: manual; 409 | hyphens: manual; 410 | } 411 | 412 | table.footnote td.label { 413 | width: .1px; 414 | padding: 0.3em 0 0.3em 0.5em; 415 | } 416 | 417 | table.footnote td { 418 | padding: 0.3em 0.5em; 419 | } 420 | 421 | dl { 422 | margin: 0; 423 | padding: 0; 424 | } 425 | 426 | dl dd { 427 | margin-left: 30px; 428 | } 429 | 430 | blockquote { 431 | margin: 0 0 0 30px; 432 | padding: 0; 433 | } 434 | 435 | ul, ol { 436 | /* Matches the 30px from the narrow-screen "li > ul" selector below */ 437 | margin: 10px 0 10px 30px; 438 | padding: 0; 439 | } 440 | 441 | pre { 442 | background: #EEE; 443 | padding: 7px 30px; 444 | margin: 15px 0px; 445 | line-height: 1.3em; 446 | } 447 | 448 | div.viewcode-block:target { 449 | background: #ffd; 450 | } 451 | 452 | dl pre, blockquote pre, li pre { 453 | margin-left: 0; 454 | padding-left: 30px; 455 | } 456 | 457 | tt, code { 458 | background-color: #ecf0f3; 459 | color: #222; 460 | /* padding: 1px 2px; */ 461 | } 462 | 463 | tt.xref, code.xref, a tt { 464 | background-color: #FBFBFB; 465 | border-bottom: 1px solid #fff; 466 | } 467 | 468 | a.reference { 469 | text-decoration: none; 470 | border-bottom: 1px dotted #004B6B; 471 | } 472 | 473 | /* Don't put an underline on images */ 474 | a.image-reference, a.image-reference:hover { 475 | border-bottom: none; 476 | } 477 | 478 | a.reference:hover { 479 | border-bottom: 1px solid #6D4100; 480 | } 481 | 482 | a.footnote-reference { 483 | text-decoration: none; 484 | font-size: 0.7em; 485 | vertical-align: top; 486 | border-bottom: 1px dotted #004B6B; 487 | } 488 | 489 | a.footnote-reference:hover { 490 | border-bottom: 1px solid #6D4100; 491 | } 492 | 493 | a:hover tt, a:hover code { 494 | background: #EEE; 495 | } 496 | 497 | 498 | @media screen and (max-width: 870px) { 499 | 500 | div.sphinxsidebar { 501 | display: none; 502 | } 503 | 504 | div.document { 505 | width: 100%; 506 | 507 | } 508 | 509 | div.documentwrapper { 510 | margin-left: 0; 511 | margin-top: 0; 512 | margin-right: 0; 513 | margin-bottom: 0; 514 | } 515 | 516 | div.bodywrapper { 517 | margin-top: 0; 518 | margin-right: 0; 519 | margin-bottom: 0; 520 | margin-left: 0; 521 | } 522 | 523 | ul { 524 | margin-left: 0; 525 | } 526 | 527 | li > ul { 528 | /* Matches the 30px from the "ul, ol" selector above */ 529 | margin-left: 30px; 530 | } 531 | 532 | .document { 533 | width: auto; 534 | } 535 | 536 | .footer { 537 | width: auto; 538 | } 539 | 540 | .bodywrapper { 541 | margin: 0; 542 | } 543 | 544 | .footer { 545 | width: auto; 546 | } 547 | 548 | .github { 549 | display: none; 550 | } 551 | 552 | 553 | 554 | } 555 | 556 | 557 | 558 | @media screen and (max-width: 875px) { 559 | 560 | body { 561 | margin: 0; 562 | padding: 20px 30px; 563 | } 564 | 565 | div.documentwrapper { 566 | float: none; 567 | background: #fff; 568 | } 569 | 570 | div.sphinxsidebar { 571 | display: block; 572 | float: none; 573 | width: 102.5%; 574 | margin: 50px -30px -20px -30px; 575 | padding: 10px 20px; 576 | background: #333; 577 | color: #FFF; 578 | } 579 | 580 | div.sphinxsidebar h3, div.sphinxsidebar h4, div.sphinxsidebar p, 581 | div.sphinxsidebar h3 a { 582 | color: #fff; 583 | } 584 | 585 | div.sphinxsidebar a { 586 | color: #AAA; 587 | } 588 | 589 | div.sphinxsidebar p.logo { 590 | display: none; 591 | } 592 | 593 | div.document { 594 | width: 100%; 595 | margin: 0; 596 | } 597 | 598 | div.footer { 599 | display: none; 600 | } 601 | 602 | div.bodywrapper { 603 | margin: 0; 604 | } 605 | 606 | div.body { 607 | min-height: 0; 608 | padding: 0; 609 | } 610 | 611 | .rtd_doc_footer { 612 | display: none; 613 | } 614 | 615 | .document { 616 | width: auto; 617 | } 618 | 619 | .footer { 620 | width: auto; 621 | } 622 | 623 | .footer { 624 | width: auto; 625 | } 626 | 627 | .github { 628 | display: none; 629 | } 630 | } 631 | 632 | 633 | /* misc. */ 634 | 635 | .revsys-inline { 636 | display: none!important; 637 | } 638 | 639 | /* Make nested-list/multi-paragraph items look better in Releases changelog 640 | * pages. Without this, docutils' magical list fuckery causes inconsistent 641 | * formatting between different release sub-lists. 642 | */ 643 | div#changelog > div.section > ul > li > p:only-child { 644 | margin-bottom: 0; 645 | } 646 | 647 | /* Hide fugly table cell borders in ..bibliography:: directive output */ 648 | table.docutils.citation, table.docutils.citation td, table.docutils.citation th { 649 | border: none; 650 | /* Below needed in some edge cases; if not applied, bottom shadows appear */ 651 | -moz-box-shadow: none; 652 | -webkit-box-shadow: none; 653 | box-shadow: none; 654 | } 655 | 656 | 657 | /* relbar */ 658 | 659 | .related { 660 | line-height: 30px; 661 | width: 100%; 662 | font-size: 0.9rem; 663 | } 664 | 665 | .related.top { 666 | border-bottom: 1px solid #EEE; 667 | margin-bottom: 20px; 668 | } 669 | 670 | .related.bottom { 671 | border-top: 1px solid #EEE; 672 | } 673 | 674 | .related ul { 675 | padding: 0; 676 | margin: 0; 677 | list-style: none; 678 | } 679 | 680 | .related li { 681 | display: inline; 682 | } 683 | 684 | nav#rellinks { 685 | float: right; 686 | } 687 | 688 | nav#rellinks li+li:before { 689 | content: "|"; 690 | } 691 | 692 | nav#breadcrumbs li+li:before { 693 | content: "\00BB"; 694 | } 695 | 696 | /* Hide certain items when printing */ 697 | @media print { 698 | div.related { 699 | display: none; 700 | } 701 | } -------------------------------------------------------------------------------- /docs/searchindex.js: -------------------------------------------------------------------------------- 1 | Search.setIndex({"docnames": ["index", "termuxgui", "termuxgui.oo"], "filenames": ["index.rst", "termuxgui.rst", "termuxgui.oo.rst"], "titles": ["termuxgui Python Documentation", "termuxgui package", "termuxgui.oo package"], "terms": {"packag": 0, "modul": 0, "subpackag": 0, "oo": [0, 1], "index": [0, 1], "search": 0, "page": 0, "thi": [1, 2], "i": 1, "librari": 1, "interact": 1, "termux": [1, 2], "gui": [1, 2], "plugin": [1, 2], "from": [1, 2], "python": 1, "you": [1, 2], "don": [1, 2], "t": [1, 2], "need": 1, "includ": 1, "all": [1, 2], "submodul": 1, "class": [1, 2], "ar": 1, "automat": 1, "scope": 1, "upon": 1, "import": 1, "activ": [1, 2], "connect": [1, 2], "tid": 1, "option": [1, 2], "str": [1, 2], "none": [1, 2], "dialog": [1, 2], "bool": [1, 2], "pip": [1, 2], "fals": [1, 2], "overlai": 1, "lockscreen": [1, 2], "canceloutsid": 1, "true": [1, 2], "intercept": [1, 2], "base": [1, 2], "object": 1, "repres": [1, 2], "an": [1, 2], "android": 1, "us": [1, 2], "c": [1, 2], "access": 1, "task": [1, 2], "finish": [1, 2], "getconfigur": 1, "configur": [1, 2], "read": 1, "current": 1, "hidesoftkeyboard": 1, "hide": 1, "soft": 1, "keyboard": 1, "ha": [1, 2], "focu": 1, "interceptbackbutton": 1, "set": 1, "whether": 1, "back": [1, 2], "button": [1, 2], "press": 1, "send": 1, "event": [1, 2], "instead": 1, "keepscreenon": 1, "should": 1, "keep": 1, "screen": 1, "while": 1, "show": 1, "movetoback": 1, "move": 1, "": 1, "recent": 1, "requestunlock": 1, "request": 1, "unlock": 1, "If": 1, "just": 1, "protect": 1, "swipe": 1, "immedi": 1, "pin": 1, "password": 1, "pattern": 1, "bring": 1, "up": 1, "ui": 1, "let": 1, "user": 1, "sendoverlayev": 1, "want": [1, 2], "receiv": 1, "setinputmod": 1, "mode": 1, "liter": [1, 2], "resiz": 1, "pan": 1, "input": 1, "setorient": 1, "orient": 1, "behind": 1, "fullsensor": 1, "fullus": 1, "landscap": 1, "lock": 1, "nosensor": 1, "portrait": 1, "reverselandscap": 1, "reverseportrait": 1, "sensorlandscap": 1, "sensorportrait": 1, "userlandscap": 1, "userportrait": 1, "prefer": 1, "setpipmod": 1, "goe": 1, "out": 1, "pictur": 1, "when": [1, 2], "exit": 1, "put": 1, "list": 1, "shown": 1, "setpipmodeauto": 1, "enter": 1, "leav": 1, "setpipparam": 1, "num": 1, "int": [1, 2], "den": 1, "paramet": 1, "onli": [1, 2], "aspect": 1, "ration": 1, "setposit": 1, "x": 1, "y": 1, "posit": 1, "settaskdescript": 1, "label": 1, "img": 1, "icon": 1, "png": 1, "jpeg": 1, "imag": 1, "base64": 1, "encod": 1, "string": 1, "setthem": 1, "statusbarcolor": 1, "colorprimari": 1, "windowbackground": 1, "textcolor": 1, "coloracc": 1, "theme": 1, "buffer": 1, "w": 1, "h": 1, "format": 1, "argb888": 1, "raw": 1, "avail": 1, "8": 1, "1": [1, 2], "consum": 1, "much": 1, "memori": 1, "so": 1, "sure": 1, "close": 1, "ani": [1, 2], "more": 1, "get": 1, "The": 1, "share": 1, "can": [1, 2], "like": 1, "byte": 1, "file": 1, "also": 1, "directli": 1, "b": 1, "mem": 1, "A": 1, "runtimeerror": 1, "rais": 1, "creat": [1, 2], "blit": 1, "underli": 1, "To": 1, "updat": 1, "imageview": [1, 2], "thei": 1, "have": 1, "refresh": 1, "afterward": 1, "remov": [1, 2], "free": 1, "text": [1, 2], "parent": [1, 2], "view": [1, 2], "allcap": [1, 2], "visibl": [1, 2], "0": [1, 2], "2": [1, 2], "textview": [1, 2], "checkbox": [1, 2], "check": [1, 2], "compoundbutton": 1, "id": [1, 2], "doesn": 1, "correspond": 1, "particular": [1, 2], "provid": 1, "common": 1, "method": 1, "handleev": 1, "e": 1, "track": 1, "pass": 1, "everi": 1, "here": [1, 2], "setcheck": 1, "explicitli": 1, "statu": 1, "contain": [1, 2], "function": [1, 2], "act": [1, 2], "checkev": 1, "least": 1, "one": [1, 2], "return": [1, 2], "g": 1, "between": 1, "draw": 1, "frame": 1, "separ": 1, "thread": 1, "block": 1, "program": 1, "good": 1, "practic": 1, "yourself": 1, "anymor": 1, "statement": 1, "iter": 1, "wait": 1, "over": 1, "incom": 1, "getvers": 1, "version": 1, "code": 1, "app": 1, "disabl": 1, "featur": 1, "present": 1, "newer": 1, "prompt": 1, "islock": 1, "devic": 1, "read_msg": [], "messag": 1, "main": 1, "socket": 1, "call": 1, "yet": 1, "implement": 1, "send_msg": 1, "msg": 1, "union": 1, "dict": 1, "send_read_msg": 1, "toast": 1, "long": 1, "displai": 1, "longer": 1, "totermux": 1, "shorthand": 1, "run": 1, "am": 1, "start": 1, "turnscreenon": 1, "turn": 1, "edittext": [1, 2], "singlelin": [1, 2], "line": [1, 2], "blockinput": [1, 2], "inputtyp": [1, 2], "textmultilin": [1, 2], "phone": [1, 2], "date": [1, 2], "time": [1, 2], "datetim": [1, 2], "number": [1, 2], "numberdecim": [1, 2], "numberpassword": [1, 2], "numbersign": [1, 2], "numberdecimalsign": [1, 2], "textemailaddress": [1, 2], "textpassword": [1, 2], "showcursor": 1, "cursor": 1, "ev": 1, "variabl": 1, "type": [1, 2], "eventtyp": 1, "valu": [1, 2], "dictionari": 1, "airplan": 1, "click": 1, "config": [1, 2], "destroi": 1, "focuschang": 1, "itemselect": 1, "kei": 1, "local": 1, "longclick": 1, "notif": 1, "notificationdismiss": 1, "notificationact": 1, "overlayscal": 1, "overlaytouch": 1, "paus": 1, "pipchang": 1, "remoteclick": 1, "resum": 1, "screen_off": 1, "screenon": 1, "screen_on": 1, "select": 1, "stop": 1, "timezon": 1, "touch": 1, "touch_cancel": 1, "cancel": 1, "touch_down": 1, "down": 1, "touch_mov": 1, "touch_pointer_down": 1, "pointer_down": 1, "touch_pointer_up": 1, "pointer_up": 1, "touch_up": 1, "userleavehint": 1, "webviewconsolemessag": 1, "webviewdestroi": 1, "webviewerror": 1, "webviewhttperror": 1, "webviewnavig": 1, "webviewprogress": 1, "framelayout": [1, 2], "viewgroup": [1, 2], "gridlayout": [1, 2], "row": [1, 2], "col": [1, 2], "horizontalscrollview": [1, 2], "fillviewport": [1, 2], "snap": [1, 2], "nobar": [1, 2], "getscrollposit": 1, "scroll": 1, "setscrollposit": 1, "smooth": 1, "specifi": [1, 2], "scoll": 1, "redraw": 1, "after": 1, "setbuff": 1, "make": 1, "sourc": 1, "setimag": 1, "linearlayout": [1, 2], "vertic": [1, 2], "nestedscrollview": [1, 2], "channel": 1, "3": [1, 2], "4": [1, 2], "createchannel": 1, "notifi": 1, "setact": 1, "action": 1, "setalertonc": 1, "alertonc": 1, "than": 1, "onc": [1, 2], "alert": 1, "setcont": 1, "custom": 1, "layout": [1, 2], "setexpandedlayout": 1, "remoteview": 1, "expand": 1, "titl": 1, "largetext": 1, "largeimag": 1, "sethudlayout": 1, "hud": 1, "seticon": 1, "setlargeimag": 1, "larg": 1, "setlargeimageasthumbnail": 1, "asthumbnail": 1, "thumbnail": 1, "collaps": 1, "setlargetext": 1, "setlayout": 1, "setongo": 1, "ongo": 1, "dismiss": 1, "setshowtimestamp": 1, "timestamp": 1, "settimestamp": 1, "unix": 1, "millisecond": 1, "settitl": 1, "progressbar": [1, 2], "setprogress": 1, "progress": 1, "integ": 1, "100": 1, "inclus": 1, "radiobutton": [1, 2], "radiogroup": [1, 2], "insid": [1, 2], "emit": [1, 2], "chang": [1, 2], "remot": 1, "widget": 1, "addbutton": 1, "could": 1, "further": 1, "manipul": 1, "addframelayout": 1, "addimageview": 1, "addlinearlayout": 1, "addprogressbar": 1, "addtextview": 1, "delet": [1, 2], "setbackgroundcolor": 1, "color": 1, "background": 1, "setpad": 1, "left": 1, "top": 1, "right": 1, "bottom": 1, "pad": 1, "max": 1, "maximum": 1, "settext": 1, "settextcolor": 1, "settexts": 1, "size": 1, "px": 1, "pixel": 1, "dip": 1, "setvis": 1, "vi": 1, "gone": 1, "hidden": 1, "still": 1, "take": 1, "space": [1, 2], "do": 1, "updatewidget": 1, "wid": 1, "empti": [1, 2], "your": [1, 2], "spinner": [1, 2], "setlist": 1, "item": 1, "swiperefreshlayout": [1, 2], "setrefresh": 1, "anim": 1, "switch": [1, 2], "tablayout": [1, 2], "selecttab": 1, "tab": 1, "It": 1, "bringtofront": 1, "front": 1, "might": 1, "requir": 1, "other": 1, "permiss": 1, "selectabletext": [1, 2], "clickablelink": [1, 2], "gettext": 1, "sendtextev": 1, "ot": 1, "setgrav": 1, "horizont": 1, "graviti": 1, "center": 1, "invert": 1, "same": 1, "togglebutton": [1, 2], "gener": [1, 2], "constant": 1, "match_par": 1, "special": 1, "wrap_cont": 1, "forcesoft": 1, "open": 1, "getdimens": 1, "width": 1, "height": 1, "handl": 1, "subclass": 1, "overrid": 1, "sendclickev": 1, "sent": 1, "sendfocuschangeev": 1, "sendlongclickev": 1, "sendtouchev": 1, "setclick": 1, "clickabl": 1, "setdimens": 1, "dimens": 1, "setwidth": 1, "setheight": 1, "setgridlayoutparam": 1, "rowsiz": 1, "colsiz": 1, "alignmentrow": 1, "baselin": 1, "fill": 1, "alignmentcol": 1, "column": 1, "defin": 1, "how": 1, "mani": 1, "cell": 1, "its": 1, "either": 1, "describ": 1, "dp": 1, "setlinearlayoutparam": 1, "weight": 1, "setmargin": 1, "margin": 1, "dir": 1, "direct": 1, "clearchildren": [1, 2], "child": [1, 2], "webview": [1, 2], "allowcontenturi": 1, "allow": 1, "load": 1, "uri": 1, "allowjavascript": 1, "javascript": 1, "execut": 1, "deni": 1, "until": 1, "respond": 1, "wheter": 1, "enabl": 1, "allownavig": 1, "navig": 1, "differ": 1, "site": 1, "evaluatej": 1, "goback": 1, "histori": 1, "goforward": 1, "forward": 1, "loaduri": 1, "setdata": 1, "data": 1, "document": 1, "abc": 2, "abstract": 2, "enum": 2, "enumer": 2, "dialog_no_cancel_outsid": 2, "5": 2, "normal": 2, "get_typ": 2, "intercept_back": 2, "on_back": 2, "on_config": 2, "on_creat": 2, "on_destroi": 2, "on_paus": 2, "on_pipchang": 2, "on_resum": 2, "on_start": 2, "on_stop": 2, "on_userleavehint": 2, "event_loop": 2, "launch": 2, "arg": 2, "kwarg": 2, "selectitem": 1}, "objects": {"": [[1, 0, 0, "-", "termuxgui"]], "termuxgui": [[1, 1, 1, "", "Activity"], [1, 1, 1, "", "Buffer"], [1, 1, 1, "", "Button"], [1, 1, 1, "", "Checkbox"], [1, 1, 1, "", "CompoundButton"], [1, 1, 1, "", "Connection"], [1, 1, 1, "", "EditText"], [1, 1, 1, "", "Event"], [1, 1, 1, "", "FrameLayout"], [1, 1, 1, "", "GridLayout"], [1, 1, 1, "", "HorizontalScrollView"], [1, 1, 1, "", "ImageView"], [1, 1, 1, "", "LinearLayout"], [1, 1, 1, "", "NestedScrollView"], [1, 1, 1, "", "Notification"], [1, 1, 1, "", "ProgressBar"], [1, 1, 1, "", "RadioButton"], [1, 1, 1, "", "RadioGroup"], [1, 1, 1, "", "RemoteViews"], [1, 1, 1, "", "Space"], [1, 1, 1, "", "Spinner"], [1, 1, 1, "", "SwipeRefreshLayout"], [1, 1, 1, "", "Switch"], [1, 1, 1, "", "TabLayout"], [1, 1, 1, "", "Task"], [1, 1, 1, "", "TextView"], [1, 1, 1, "", "ToggleButton"], [1, 1, 1, "", "View"], [1, 1, 1, "", "ViewGroup"], [1, 1, 1, "", "WebView"], [2, 0, 0, "-", "oo"]], "termuxgui.Activity": [[1, 2, 1, "", "finish"], [1, 2, 1, "", "getconfiguration"], [1, 2, 1, "", "hidesoftkeyboard"], [1, 2, 1, "", "interceptbackbutton"], [1, 2, 1, "", "keepscreenon"], [1, 2, 1, "", "movetoback"], [1, 2, 1, "", "requestunlock"], [1, 2, 1, "", "sendoverlayevents"], [1, 2, 1, "", "setinputmode"], [1, 2, 1, "", "setorientation"], [1, 2, 1, "", "setpipmode"], [1, 2, 1, "", "setpipmodeauto"], [1, 2, 1, "", "setpipparams"], [1, 2, 1, "", "setposition"], [1, 2, 1, "", "settaskdescription"], [1, 2, 1, "", "settheme"]], "termuxgui.Buffer": [[1, 2, 1, "", "blit"], [1, 2, 1, "", "remove"]], "termuxgui.CompoundButton": [[1, 2, 1, "", "handleevent"], [1, 2, 1, "", "setchecked"]], "termuxgui.Connection": [[1, 2, 1, "", "checkevent"], [1, 2, 1, "", "close"], [1, 2, 1, "", "events"], [1, 2, 1, "", "getversion"], [1, 2, 1, "", "islocked"], [1, 2, 1, "", "send_msg"], [1, 2, 1, "", "send_read_msg"], [1, 2, 1, "", "toast"], [1, 2, 1, "", "totermux"], [1, 2, 1, "", "turnscreenon"]], "termuxgui.EditText": [[1, 2, 1, "", "showcursor"]], "termuxgui.Event": [[1, 3, 1, "", "airplane"], [1, 3, 1, "", "back"], [1, 3, 1, "", "click"], [1, 3, 1, "", "config"], [1, 3, 1, "", "create"], [1, 3, 1, "", "destroy"], [1, 3, 1, "", "focusChange"], [1, 3, 1, "", "itemselected"], [1, 3, 1, "", "key"], [1, 3, 1, "", "locale"], [1, 3, 1, "", "longClick"], [1, 3, 1, "", "notification"], [1, 3, 1, "", "notificationDismissed"], [1, 3, 1, "", "notificationaction"], [1, 3, 1, "", "overlayScale"], [1, 3, 1, "", "overlaytouch"], [1, 3, 1, "", "pause"], [1, 3, 1, "", "pipchanged"], [1, 3, 1, "", "refresh"], [1, 3, 1, "", "remoteclick"], [1, 3, 1, "", "resume"], [1, 3, 1, "", "screen_off"], [1, 3, 1, "", "screenon"], [1, 3, 1, "", "selected"], [1, 3, 1, "", "start"], [1, 3, 1, "", "stop"], [1, 3, 1, "", "text"], [1, 3, 1, "", "timezone"], [1, 3, 1, "", "touch"], [1, 3, 1, "", "touch_cancel"], [1, 3, 1, "", "touch_down"], [1, 3, 1, "", "touch_move"], [1, 3, 1, "", "touch_pointer_down"], [1, 3, 1, "", "touch_pointer_up"], [1, 3, 1, "", "touch_up"], [1, 3, 1, "", "userleavehint"], [1, 3, 1, "", "webviewConsoleMessage"], [1, 3, 1, "", "webviewDestroyed"], [1, 3, 1, "", "webviewError"], [1, 3, 1, "", "webviewHTTPError"], [1, 3, 1, "", "webviewNavigation"], [1, 3, 1, "", "webviewProgress"]], "termuxgui.HorizontalScrollView": [[1, 2, 1, "", "getscrollposition"], [1, 2, 1, "", "setscrollposition"]], "termuxgui.ImageView": [[1, 2, 1, "", "refresh"], [1, 2, 1, "", "setbuffer"], [1, 2, 1, "", "setimage"]], "termuxgui.NestedScrollView": [[1, 2, 1, "", "getscrollposition"], [1, 2, 1, "", "setscrollposition"]], "termuxgui.Notification": [[1, 2, 1, "", "cancel"], [1, 2, 1, "", "createchannel"], [1, 2, 1, "", "notify"], [1, 2, 1, "", "setactions"], [1, 2, 1, "", "setalertonce"], [1, 2, 1, "", "setcontent"], [1, 2, 1, "", "setexpandedlayout"], [1, 2, 1, "", "sethudlayout"], [1, 2, 1, "", "seticon"], [1, 2, 1, "", "setlargeimage"], [1, 2, 1, "", "setlargeimageasthumbnail"], [1, 2, 1, "", "setlargetext"], [1, 2, 1, "", "setlayout"], [1, 2, 1, "", "setongoing"], [1, 2, 1, "", "setshowtimestamp"], [1, 2, 1, "", "settimestamp"], [1, 2, 1, "", "settitle"]], "termuxgui.ProgressBar": [[1, 2, 1, "", "setprogress"]], "termuxgui.RemoteViews": [[1, 2, 1, "", "addButton"], [1, 2, 1, "", "addFrameLayout"], [1, 2, 1, "", "addImageView"], [1, 2, 1, "", "addLinearLayout"], [1, 2, 1, "", "addProgressBar"], [1, 2, 1, "", "addTextView"], [1, 2, 1, "", "delete"], [1, 2, 1, "", "setBackgroundColor"], [1, 2, 1, "", "setImage"], [1, 2, 1, "", "setPadding"], [1, 2, 1, "", "setProgress"], [1, 2, 1, "", "setText"], [1, 2, 1, "", "setTextColor"], [1, 2, 1, "", "setTextSize"], [1, 2, 1, "", "setVisibility"], [1, 2, 1, "", "updateWidget"]], "termuxgui.Spinner": [[1, 2, 1, "", "selectitem"], [1, 2, 1, "", "setlist"]], "termuxgui.SwipeRefreshLayout": [[1, 2, 1, "", "setrefreshing"]], "termuxgui.TabLayout": [[1, 2, 1, "", "selecttab"], [1, 2, 1, "", "setlist"]], "termuxgui.Task": [[1, 2, 1, "", "bringtofront"], [1, 2, 1, "", "finish"]], "termuxgui.TextView": [[1, 2, 1, "", "gettext"], [1, 2, 1, "", "sendtextevent"], [1, 2, 1, "", "setgravity"], [1, 2, 1, "", "settext"], [1, 2, 1, "", "settextcolor"], [1, 2, 1, "", "settextsize"]], "termuxgui.View": [[1, 3, 1, "", "GONE"], [1, 3, 1, "", "HIDDEN"], [1, 3, 1, "", "MATCH_PARENT"], [1, 3, 1, "", "VISIBLE"], [1, 3, 1, "", "WRAP_CONTENT"], [1, 2, 1, "", "delete"], [1, 2, 1, "", "focus"], [1, 2, 1, "", "getdimensions"], [1, 2, 1, "", "handleevent"], [1, 2, 1, "", "sendclickevent"], [1, 2, 1, "", "sendfocuschangeevent"], [1, 2, 1, "", "sendlongclickevent"], [1, 2, 1, "", "sendtouchevent"], [1, 2, 1, "", "setbackgroundcolor"], [1, 2, 1, "", "setclickable"], [1, 2, 1, "", "setdimensions"], [1, 2, 1, "", "setgridlayoutparams"], [1, 2, 1, "", "setheight"], [1, 2, 1, "", "setlinearlayoutparams"], [1, 2, 1, "", "setmargin"], [1, 2, 1, "", "setvisibility"], [1, 2, 1, "", "setwidth"]], "termuxgui.ViewGroup": [[1, 2, 1, "", "clearchildren"]], "termuxgui.WebView": [[1, 2, 1, "", "allowcontenturi"], [1, 2, 1, "", "allowjavascript"], [1, 2, 1, "", "allownavigation"], [1, 2, 1, "", "evaluatejs"], [1, 2, 1, "", "goback"], [1, 2, 1, "", "goforward"], [1, 2, 1, "", "loaduri"], [1, 2, 1, "", "setdata"]], "termuxgui.oo": [[2, 1, 1, "", "Activity"], [2, 1, 1, "", "Button"], [2, 1, 1, "", "Checkbox"], [2, 1, 1, "", "Connection"], [2, 1, 1, "", "EditText"], [2, 1, 1, "", "FrameLayout"], [2, 1, 1, "", "GridLayout"], [2, 1, 1, "", "HorizontalScrollView"], [2, 1, 1, "", "ImageView"], [2, 1, 1, "", "LinearLayout"], [2, 1, 1, "", "NestedScrollView"], [2, 1, 1, "", "ProgressBar"], [2, 1, 1, "", "RadioButton"], [2, 1, 1, "", "RadioGroup"], [2, 1, 1, "", "Space"], [2, 1, 1, "", "Spinner"], [2, 1, 1, "", "SwipeRefreshLayout"], [2, 1, 1, "", "Switch"], [2, 1, 1, "", "TabLayout"], [2, 1, 1, "", "TextView"], [2, 1, 1, "", "ToggleButton"], [2, 1, 1, "", "View"], [2, 1, 1, "", "ViewGroup"], [2, 1, 1, "", "WebView"]], "termuxgui.oo.Activity": [[2, 1, 1, "", "Type"], [2, 2, 1, "", "get_type"], [2, 2, 1, "", "intercept_back"], [2, 2, 1, "", "on_back"], [2, 2, 1, "", "on_config"], [2, 2, 1, "", "on_create"], [2, 2, 1, "", "on_destroy"], [2, 2, 1, "", "on_pause"], [2, 2, 1, "", "on_pipchanged"], [2, 2, 1, "", "on_resume"], [2, 2, 1, "", "on_start"], [2, 2, 1, "", "on_stop"], [2, 2, 1, "", "on_userleavehint"]], "termuxgui.oo.Activity.Type": [[2, 3, 1, "", "DIALOG"], [2, 3, 1, "", "DIALOG_NO_CANCEL_OUTSIDE"], [2, 3, 1, "", "LOCKSCREEN"], [2, 3, 1, "", "NORMAL"], [2, 3, 1, "", "PIP"]], "termuxgui.oo.Connection": [[2, 2, 1, "", "event_loop"], [2, 2, 1, "", "launch"]], "termuxgui.oo.View": [[2, 2, 1, "", "delete"]], "termuxgui.oo.ViewGroup": [[2, 2, 1, "", "clearchildren"]]}, "objtypes": {"0": "py:module", "1": "py:class", "2": "py:method", "3": "py:attribute"}, "objnames": {"0": ["py", "module", "Python module"], "1": ["py", "class", "Python class"], "2": ["py", "method", "Python method"], "3": ["py", "attribute", "Python attribute"]}, "titleterms": {"welcom": [], "termuxgui": [0, 1, 2], "": [], "document": 0, "content": [0, 1, 2], "indic": 0, "tabl": 0, "packag": [1, 2], "modul": [1, 2], "subpackag": 1, "oo": 2, "python": 0}, "envversion": {"sphinx.domains.c": 2, "sphinx.domains.changeset": 1, "sphinx.domains.citation": 1, "sphinx.domains.cpp": 6, "sphinx.domains.index": 1, "sphinx.domains.javascript": 2, "sphinx.domains.math": 2, "sphinx.domains.python": 3, "sphinx.domains.rst": 2, "sphinx.domains.std": 2, "sphinx": 56}}) --------------------------------------------------------------------------------