Karana.WebUI
============

.. py:module:: Karana.WebUI

.. autoapi-nested-parse::

   Classes and modules related to Web UI.



Submodules
----------

.. toctree::
   :maxdepth: 1

   /generated/python_api/Karana/WebUI/easydock/index
   /generated/python_api/Karana/WebUI/selenium/index


Attributes
----------

.. autoapisummary::

   Karana.WebUI.Json


Classes
-------

.. autoapisummary::

   Karana.WebUI.Button
   Karana.WebUI.Channel
   Karana.WebUI.ClientApp
   Karana.WebUI.ContentSource
   Karana.WebUI.Dock
   Karana.WebUI.Dropdown
   Karana.WebUI.HttpWsServer
   Karana.WebUI.IFrame
   Karana.WebUI.InputGroup
   Karana.WebUI.Layout
   Karana.WebUI.Markdown
   Karana.WebUI.QuantityInput
   Karana.WebUI.Router
   Karana.WebUI.Selection
   Karana.WebUI.Server
   Karana.WebUI.Slider
   Karana.WebUI.SliderOptions
   Karana.WebUI.State
   Karana.WebUI.Toggle
   Karana.WebUI.TreeView
   Karana.WebUI.Widget


Package Contents
----------------

.. py:type:: Json
   :canonical: None | str | int | float | list['Json'] | dict[str, 'Json']


.. py:class:: Button(router: Router, text: str, on_press: collections.abc.Callable[[], None], tooltip: str = '')

   Bases: :py:obj:`Widget`


.. py:class:: Channel

   .. py:method:: broadcastMessage(msg: str) -> None


   .. py:method:: defer(callback: collections.abc.Callable[[], None]) -> None


   .. py:method:: sendMessage(msg: str, client_id: SupportsInt | SupportsIndex) -> None


   .. py:method:: setOnConnect(callback: collections.abc.Callable[[SupportsInt | SupportsIndex], None]) -> None


   .. py:method:: setOnDisconnect(callback: collections.abc.Callable[[SupportsInt | SupportsIndex], None]) -> None


   .. py:method:: setOnMessage(callback: collections.abc.Callable[[str, SupportsInt | SupportsIndex], None]) -> None


   .. py:method:: sync() -> None


   .. py:method:: uuid() -> str


.. py:class:: ClientApp(url: str)

   .. py:method:: findExecutable() -> pathlib.Path | None
      :staticmethod:



   .. py:method:: getStderr() -> str


   .. py:method:: getStdout() -> str


   .. py:method:: shutdown() -> None


.. py:class:: ContentSource

.. py:class:: Dock(router: Router, style: collections.abc.Mapping[str, str] = {})

   Bases: :py:obj:`Widget`


   .. py:method:: addChild(title: str, widget: Widget) -> None
                  addChild(title: str, widget: Widget, relative_to: Widget, direction: str = '') -> None


.. py:class:: Dropdown(router: Router, text: str, choices: collections.abc.Sequence[str], on_change: collections.abc.Callable[[SupportsInt | SupportsIndex], None] = None, value_state: State = None)

   Bases: :py:obj:`Widget`


   .. py:method:: setIndex(index: SupportsInt | SupportsIndex) -> None

      Set the current index of the dropdown

      :param index: The index of the current dropdown item



.. py:class:: HttpWsServer(port: SupportsInt | SupportsIndex)

   .. py:method:: broadcastMessage(msg: bytes) -> None

      Broadcast binary data to all clients.



   .. py:method:: close() -> None


   .. py:method:: defer(callback: collections.abc.Callable[[], None]) -> None


   .. py:method:: getPort() -> int


   .. py:method:: getUrl() -> str


   .. py:method:: printConnectionInfo() -> None

      Print info to stdout about how to connect



   .. py:method:: sendMessage(msg: bytes, client_id: SupportsInt | SupportsIndex) -> None

      Send binary data to a specific client.



   .. py:method:: serveCasData(content: str, url_prefix: str = '', headers: collections.abc.Sequence[tuple[str, str]] = []) -> str


   .. py:method:: serveCasFile(path: os.PathLike | str | bytes, url_prefix: str = '', headers: collections.abc.Sequence[tuple[str, str]] = []) -> str


   .. py:method:: serveData(url: str, content: str, headers: collections.abc.Sequence[tuple[str, str]] = []) -> None


   .. py:method:: serveFile(url: str, path: os.PathLike | str | bytes, headers: collections.abc.Sequence[tuple[str, str]] = []) -> None


   .. py:method:: setOnConnect(callback: collections.abc.Callable[[SupportsInt | SupportsIndex], None]) -> None


   .. py:method:: setOnDisconnect(callback: collections.abc.Callable[[SupportsInt | SupportsIndex], None]) -> None


   .. py:method:: setOnMessage(callback: collections.abc.Callable[[str, SupportsInt | SupportsIndex], None]) -> None


   .. py:method:: sync() -> None


   .. py:method:: waitForClients(clients: SupportsInt | SupportsIndex = 1, timeout: SupportsFloat | SupportsIndex = 0.0) -> bool

      Wait for a given number of clients to connect.
      :param clients:
                      - Number of clients to wait for
      :param timeout_seconds:
                              - Timeout, if positive

      :returns: True if the requested client count was reached



.. py:class:: IFrame(router: Router, url: str)

   Bases: :py:obj:`Widget`


.. py:class:: InputGroup(router: Router, title: str = '', style: collections.abc.Mapping[str, str] = {})

   Bases: :py:obj:`Widget`


   .. py:method:: addChild(widget: Widget) -> None


.. py:class:: Layout(router: Router, style: collections.abc.Mapping[str, str] = {})

   Bases: :py:obj:`Widget`


   .. py:method:: addChild(widget: Widget) -> None


.. py:class:: Markdown(router: Router, text: str, in_line: bool = False)

   Bases: :py:obj:`Widget`


   .. py:method:: setText(text: str) -> None


.. py:class:: QuantityInput(router: Router, text: str, on_change: collections.abc.Callable[[SupportsFloat | SupportsIndex, str], None] = None, quantity_state: State = None)

   Bases: :py:obj:`Widget`


.. py:class:: Router(server: HttpWsServer)

   .. py:method:: channel(esm: Any = '', css: Any = '', init_msg: str = '') -> Channel


.. py:class:: Selection(items: collections.abc.Sequence[Selection] = [])

   .. py:class:: Item(id: SupportsInt | SupportsIndex, context: Karana.WebUI.Json = None)

      .. py:attribute:: context
         :type:  Karana.WebUI.Json


      .. py:property:: id
         :type: int




   .. py:method:: parse(j: Karana.WebUI.Json) -> Selection
      :staticmethod:



   .. py:method:: dump() -> Karana.WebUI.Json


   .. py:property:: items
      :type: list[Selection]



.. py:class:: Server(port: SupportsInt | SupportsIndex = 8765)

   .. py:method:: canFindLocalClientExecutable() -> bool
      :staticmethod:


      Check if the client executable can be found....
      :returns: Whether the client executable can be found



   .. py:method:: closeLocalClients() -> None

      Close all managed clients.



   .. py:method:: guessUrl() -> str

      Generate a URL to connect to the sever.

      Note that this URL is a best guess from the point of view of the
      server. It may not reflect the publicly accessible URL for the server.

      :returns: The URL guess



   .. py:method:: launchLocalClient(*, silent: bool = True) -> None

      Spawn a managed electron client as a subprocess.
      :param options:
                      - Parameters struct for the local client.



   .. py:method:: onThread() -> bool

      Check whether the current thread is the io thread
      :returns: Whether the current thread is the io thread



   .. py:method:: port() -> int

      Get the port the server is bound to.
      :returns: The port number.



   .. py:method:: printConnectionInfo() -> None

      Print info to stdout about how to connect



   .. py:method:: sync() -> None

      Wait for currently queued tasks to complete



   .. py:method:: waitForClients(clients: SupportsInt | SupportsIndex = 1, timeout_seconds: SupportsFloat | SupportsIndex = 0.0) -> None

      Wait for a given number of clients to connect.
      :param clients:
                      - Number of clients to wait for.
      :param timeout:
                      - Timeout in seconds, if positive



.. py:class:: Slider(router: Router, text: str, on_change: collections.abc.Callable[[SupportsFloat | SupportsIndex], None] = None, opts: SliderOptions = None, value_state: State = None)

   Bases: :py:obj:`Widget`


   .. py:method:: setMax(max: SupportsFloat | SupportsIndex) -> None

      Set the max value of the slider
      :param max: The upper bound on possible values



   .. py:method:: setMin(min: SupportsFloat | SupportsIndex) -> None

      Set the min value of the slider
      :param min: The lower bound on possible values



   .. py:method:: setStep(step: SupportsFloat | SupportsIndex) -> None

      Set the step size of the slider
      :param step: The step size of values on the slider



   .. py:method:: setValue(value: SupportsFloat | SupportsIndex) -> None

      Set the current value of the slider
      :param value: The value of the slider



.. py:class:: SliderOptions

   Widget displaying a Slider triggering a server-side callback


   .. py:property:: log_scale
      :type: bool


      Whether to use log scale (currently unsupported)


   .. py:property:: max
      :type: float


      Upper bound on possible values


   .. py:property:: min
      :type: float


      Lower bound on possible values


   .. py:property:: step
      :type: float


      Step size of values on slider


   .. py:property:: tooltip
      :type: str


      Tooltip to display on hover (if any)


.. py:class:: State(router: Router, init_value: Karana.WebUI.Json = None, sync: bool = True)

   .. py:method:: cancelOnChange(id: SupportsInt | SupportsIndex) -> None


   .. py:method:: channel() -> Channel


   .. py:method:: get() -> Karana.WebUI.Json


   .. py:method:: onChange(on_change: collections.abc.Callable[[Karana.WebUI.Json], None]) -> int


   .. py:method:: set(new_value: Karana.WebUI.Json, skip_id: SupportsInt | SupportsIndex | None = None) -> None


.. py:class:: Toggle(router: Router, text: str, on_toggle: collections.abc.Callable[[bool], None], tooltip: str = '', render_as_button: bool = False, toggle_state: State = None)

   Bases: :py:obj:`Widget`


   .. py:method:: setValue(on: bool) -> None

      Set the current value of the toggle
      :param on: Whether the toggle should be set to on



.. py:class:: TreeView(router: Router, nodes: collections.abc.Sequence[TreeView] = [], edges: collections.abc.Sequence[TreeView] = [], on_select: collections.abc.Callable[[Selection], None] = None, on_refresh: collections.abc.Callable[[], None] = None, selection: State = None)

   Bases: :py:obj:`Widget`


   .. py:class:: Edge(parent_id: SupportsInt | SupportsIndex, child_id: SupportsInt | SupportsIndex)

      .. py:property:: child_id
         :type: int



      .. py:property:: parent_id
         :type: int




   .. py:class:: Node(id: SupportsInt | SupportsIndex, label: str = 'unnamed', style_class: str = '', tooltip: str = '', collapsed: bool = False)

      .. py:attribute:: collapsed
         :type:  bool


      .. py:attribute:: label
         :type:  str


      .. py:attribute:: style_class
         :type:  str


      .. py:attribute:: tooltip
         :type:  str


      .. py:property:: id
         :type: int




   .. py:method:: refresh() -> None

      Forces a refresh of the TreeView via its `on_refresh()` callback, if
      any was set.

      Do not call this from the `on_refresh` callback itself, since that
      would create a cycle.



   .. py:method:: select(selection: Selection) -> None


   .. py:method:: setNodeLabel(id: SupportsInt | SupportsIndex, label: str) -> None


   .. py:method:: setTree(nodes: collections.abc.Sequence[TreeView], edges: collections.abc.Sequence[TreeView]) -> None


.. py:class:: Widget(router: Router, esm: Any = '', css: Any = '', states: collections.abc.Mapping[str, State] = {}, style: collections.abc.Mapping[str, str] = {}, init_msg: str = '')

   .. py:method:: addDomClass(dom_class: str) -> None


   .. py:method:: addToDomRoot() -> None


   .. py:method:: channel() -> Channel


   .. py:method:: domId() -> str


   .. py:method:: removeDomClass(dom_class: str) -> None


   .. py:method:: setEnabled(enabled: bool) -> None


   .. py:method:: setVisible(flag: bool) -> None


   .. py:method:: state(name: str) -> State


