Stellarium
24.3
|
The RemoteControl plugin, by default, provides a HTML web interface through the same integrated HTTP server that serves the RemoteControl API. All content found in the data/webroot
folder is served. Note that the /api/
path is reserved for the HTTP API, and therefore can not be used as a folder. The index.html
file is mapped to the root, so you can access it using http://localhost:8090 with the default port setting of 8090. A slightly modified alternative interface (mainly larger buttons for now) for 7" tablets and other touch devices is available at http://localhost:8090/tablet7in.html.
A reasonably modern browser is required to access the interface. Some features of HTML5 and CSS3 are used.
The interface heavily relies on jQuery for easier JavaScript coding. The code is structured into modules, and loaded using require.js, which automatically resolves dependencies and load order.
Note that not all files are listed here, only those of special interest.
With knowledge of HTML, CSS and JavaScript (the latter not required for basic modifications), the interface can be customized.
When using the standard JavaScript provided, they allow to use pre-defined CSS "marker" classes which do not style the element per-se (i.e. have no entries in the .css files), but allow you to add functionality to HTML elements without editing the JavaScript code. Some of these classes also allow you to add further attributes to the element (usually HTML5 data attributes) to further customize their behaviour.
Some classes allow generating UI controls that are similar to what you expect for desktop apps. These use jQuery UI with some modifications.
If added to an HTML input
element, it sets the control up as a numerical Spinner widget (using jQuery UI: https://api.jqueryui.com/spinner/). It supports the following optional parameters:
data-min
- Defines the minimum value of the spinnerdata-max
- Defines the maximum value of the spinnerdata-step
- Defines the desired step size of the spinner, default is 1. May be different from the number format.data-numberformat
- Defines how the number is formatted, using globalize.js 0.1.1 syntaxThe element will emit the custom spinuserinput
event whenever the value changes (either through the buttons or direct keyboard input). An example, showing how a spinner is created and handled:
If added to an HTML div
element, it sets the control up as a numerical slider widget (using jQuery UI: https://api.jqueryui.com/slider/). It supports the following optional parameters:
data-min
- Defines the minimum value of the sliderdata-max
- Defines the maximum value of the sliderdata-step
- Defines the desired step size of the slider, default is 1. May be different from the number format.The element will emit the slide
event when the slider is moved.
If added to an HTML button
element, it converts it to a jQuery UI button. This is mainly a cosmetic operation.
If added to an HTML select
element, it creates a jQuery UI selectmenu from it. This allows simple popup selection menus (like a QComboBox).
These classes allow automatic connection to StelProperty and StelAction elements defined in Stellarium, allowing particularly easy extension of the web interface.
Allows direct connection of an element to a StelProperty, meaning the element is automatically updated whenever the value in Stellarium changes — regardless of the source of the change: it can come from the main GUI, scripting, or even other RemoteControl web interface instances! Together with the UI control classes listed above, this allows closely and easily recreating standard Stellarium interface elements. This is supported for:
input
elements with the spinner
class (for numerical properties)input
attribute name
. Updates the value
property of the input
when the StelProperty changes, and reacts to spinuserinput
events to update the propertyinput
elements of type checkbox
(<input type="checkbox">
(for boolean properties)input
attribute name
. Uses the checked
property and the click
event.div
elements with the slider
class (for numerical properties)data-prop
. Connects to the slider
widget property value
.select
elements (also supports the optional selectmenu
class)select
attribute name
. Sets the option
that has the same value
as the StelProperty value. Useful for single selection out of a list of possibilities.span
elements, for read-only property display with optional number formatdata-prop
. The value is displayed using the element's text content. The optional data-numberformat
attribute is used for the number format using globalize.js 0.1.1 syntaxbutton
or input[type="button"]
elements, for write-only setting of a StelProperty to a pre-defined value when clickedname
, and the value to set it to is defined by the attribute value
.An example, setting up a spinner for the MilkyWay.intensity
StelProperty:
Many more examples can be found by studying the index.html
code.
When this class is added to button
elements or input
elements of type="button"
or type="checkbox"
, this connects the control to a StelAction. The action is identified by the name
attribute. If the action is a boolean action (i.e. StelAction::isCheckable is true), checkboxes show the current state of the action, and buttons get the active
CSS class assigned if the action is currently true.
Examples:
This class allows you to define buttons that directly execute Stellarium Scripting Engine code. Supported for button
and input
elements of type button
. The code to execute should be stored inside the element's value
property. If the custom attribute data-useincludes
attribute is added (with any value), the default include folder is added for optional includes, but this is not recommended unless necessary.
An example:
stelssc
approach has some disadvantages, so try to use it only when necessary:stelssc
buttons!With the CSS class stelplugin
, one can create special HTML sections that are only shown when a specified plugin is currently loaded by Stellarium. If the plugin is not loaded, the whole element and all it's children are removed from the DOM. This class can be added to any element. The plugin which is required is defined by the data-plugin
attribute, which should be set to the plugin ID.
The optional data-pluginjs
attribute can be used to define an additional JavaScript module that is only loaded when the plugin is loaded. This can be used to implement additional behaviour through JS, if required. It is recommended to put these modules into the webroot/js/plugins
folder.
An example, defining the plugin panel for the ArchaeoLines Plug-in :
The interface can be translated using methods similar to the main program. All strings in the HTML markup that should be translated can be written between pseudo-PHP style tags and the tr
function to achieve the same effect as the q_()
macro in C++, like so:
All files which are listed in the webroot/translate_files
file will be parsed, and all <?= tr("----")?>
tags will be replaced using the StelTranslator for the current application language.
If you require translated strings through JavaScript, you should use the tr
method of the api/remotecontrol module, which also works similar to the q_()
macro. There is a special procedure for the JavaScript strings: the target RemoteControl-update-translationdata
should be run whenever new JavaScript strings have been added. This updates the file webroot/js/translationdata.js
with all current tr()
strings. Python is required to be installed for this operation.
Like the main program, the strings can be extracted from the HTML/JS code using gettext/xgettext. There are CMake targets for this like for the C++ code (generate-pot-stellarium-remotecontrol
, update-po-stellarium-remotecontrol
, etc.) and they are also executed with the combined targets (generate-pot
, update-po
etc.).
All interface code is developed using require.js modules. This allows defining the dependencies of each module, as well as easier maintainability. Each module should be defined in its own .js file. The module ID corresponds to the .js file name without the file extension.
In short, to define a module, wrap it in a define
call, and optionally add dependencies. A basic example (for more ways to do it see the require.js doc):
The UI modules can depend on the API modules and other UI modules. The API modules can depend on other API modules. Circular dependencies should of course be avoided.
This is the main API module, with no further dependencies on other API modules.
Its main function is that it provides automatic status updates by periodically polling (by default each second) the status
operation of the MainService. Whenever this poll succeeds, the serverDataReceived
custom event is emitted, with the JSON response of the server as data
parameter. Other API modules should use this event, and process the data in which they are interested. It also keeps track of StelAction and StelProperty changes, and emits stelActionsChanged
and/or stelPropertiesChanged
, if necessary. Note that it does not process them further, this is the job of the api/actions and api/properties modules, respectively. When the connection to the server is lost (i.e. the polling returned an error), the serverDataError
event is sent.
The other main function is that it provides the postCmd
method, which is a simple wrapper around an AJAX POST call that is intended to be used by other modules to send commands to the server. It also includes the tr
method used for translating JS strings.
Finally, this module also processes the plugin-specific sections on load.
Processes StelAction related events. Whenever it detects that boolean StelAction was changed, it emits two events:
stelActionChanged
with the actionId
as a parameter. This can be used when interested in ALL action changes (like for a action list)stelActionChanged:<actionId>
with the actionId
as part of the event name. This can be used when listening for a specific action only.On the first load of the interface, it loads a list of all actions (using the ActionService list
operation) and emits the actionListLoaded
event when this data is available.
To execute/toggle an action, it provides the public executeAction
method, which just requires the action ID as parameter. To find out whether an action is currently checked, use the isChecked
method.
This is a utility module, which can be used to implement checkboxes for enum flag types, where each checkbox sets a specific bit of a single value. The module should be constructed with new
, the constructor takes the parent element of a list of checkboxes (input
of type checkbox) and a method which is called back when the internal value changes (i.e. the user clicks a checkbox). It provides the setValue
method to set the current value and check the correct checkboxes. The bit value of each input
should be specified as its value
property, in hexadecimal string format (for example 0x0004
)
Module which connects to the LocationService and the LocationSearchService. It emits the following events whenever the specified field changed: planetChanged
,nameChanged
, countryChanged
, altitudeChanged
, latitudeChanged
, longitudeChanged
, positionChanged
(emitted when either lat or lon changed)
It also has set
methods for these fields. Furthermore, it provides performLocationSearch
, which searches the predefined locations for a specific search string, and performNearbySearch
, which searches predefined locations near a given lat/lon on the current planet. These methods take a callback parameter to notify the caller of the results. The setLocationById
method can then be used to set the location to a result of these 2 methods.
It also provides a loadCountryList
and a loadPlanetList
which load the specified lists and return the results with a callback.
Processes StelProperty related things. Like the api/actions module, it emits 2 events when it detects a StelProperty changed:
stelPropertyChanged
with the propertyId
as a parameter. This can be used when interested in ALL property changes (like for a list)stelPropertyChanged:<propertyId>
with the propertyId
as part of the event name. This can be used when listening for a specific property only.It provides getStelProp
and setStelProp
methods which retrieve and set the value of a StelProperty, and also a setStelPropQueued
convenience method to batch multiple fast interface changes (e.g. through a slider or spinner) into a single setStelProp
call which is only executed after a small time has passed with no changes.
It also emits the propertyListLoaded
event when it first loads the full list of StelProperties with their type information.
This module handles script execution (i.e. connection to the ScriptService). It provides the following methods:
loadScriptList
- loads the list of all scripts, takes a callback to return this datarunScript
- runs the specified script idrunDirectScript
- directly runs the given script codestopScript
- stops a currently running scriptIt also emits the activeScriptChanged
event whenever it detects that the current script has changed or started/stopped
Implements object search functionality, connecting to the ObjectService and the SimbadService. The following methods are provided:
loadObjectTypes
- loads the list of object types, takes a callbackloadObjectList
- loads the list of objects of a specified type, can return english or localized namesselectObjectByName
- selects the object that matches the specified namefocusPosition
- focuses the given coordinate (array of 3 numbers) in the J2000 frameperformSearch
- performs an object lookup in Stellarium's internal catalog and Simbad. In addition to the search string, 2 callbacks must be given as parameters: one for the catalog results, and one for the simbad results. If a search is currently running, it is aborted (meaning the callbacks won't be called for the old searches), allowing this method to be repeatedly called while the user is typing. The Simbad search is only started after a small interval without typing, to reduce the overhead of the external web requests.While a search is running, it emits simbadStateChange
events to notify the UI of the current state of the lookup.
Contains time-related functions and conversions, similar to what StelCore does. This module keeps it's own sense of Stellariums current time, to provide an updated interface even between the status
polls of the api/remotecontrol module.
It provides following methods:
getCurrentTime
- calculates the best guess to the current Stellarium simulation time. This depends on the information received with the last status
poll, the time since the last data was received and the time the last time change was performedisRealTimeSpeed
- true if the simulation time currently flows at the same rate as the real time (1 sec per sec).jdayToDate
- converts a jDay (single number) to Day/Month/Year format, this returns a JS object with day
, month
, year
fields instead of a JS Date object because of its limitations.jdayToDate
- returns the time component of the given jDay, as a JS object with hour
, minute
, second
fieldsdateTimeToJd
- converts a time given in Y/M/D-H/MIN/S format to a jDaydateTimeForRollover
- like StelUtils::changeDateTimeForRolloverisTimeUpdatePending
- if true, there is a time change which has not yet been sent to the serverincreaseTimeRate
- increases the Stellarium simulation time rate (like StelCore::increaseTimeSpeed)decreaseTimeRate
- decreases the Stellarium simulation time rate (like StelCore::decreaseTimeSpeed)isRewind
- returns true if the time currently flows backwards (at least at -0.99 sec / sec)isFastForward
- returns true if time currently is flowing faster than real timeisTimeNow
- returns true if the current simulation time is very close to the actual system timeisTimeStopped
- returns true if the simulation time rate is zerotogglePlayPause
- toggles between timerates 0 and 1 sec/secsetDateNow
- sets the simulation time to the current system timesetJDay
- sets the time to the specified JDaysetTimeFromTimeObj
- sets the time from a "time object", containing both date and time in the following format getTimeData
- returns the current time data, containing the last response from the server (including timezone info, etc) The event timeDataUpdated
is sent whenever this changes.This implements a simple update queue class that updates the server after a specified interval if the user does nothing else inbetween. This is used to limit the rate at which updates are sent to the server. The UpdateQueue
constructor takes an url and a callback for the result, and when the interface needs to send an update, enqueue
can be called with the data to send.
Implements the FOV access and viewport movement methods. Use setFOV
to set the FOV, the fovChanged
event is sent whenever the FOV changes. There are moveRight
, moveUp
, moveUpRight
etc. methods that allow the user to move the viewport. To stop the movement, use stopMovement
.
Implements the loading of the projection, landscape and skyculture lists.
This is the main module of the interface. It lists all the other UI modules as a dependency. It starts of the update look of the rcApiRemotecontrol
module, handles the automatic generation of the special controls and connection of StelProperty controls, and performs smooth animation of the time controls. It also keeps track of the current interface tab the user is on, and restores it when the page is reloaded.
Implements the action list and the StelAction buttons and checkboxes.
Implements a custom combobox control, on top of the jQuery UI autocomplete
control. This is used for example in the location controls.
Includes some fixes to the standard jQuery UI control classes, especially for the spinner, to provide a unified change event, prevent non-numeric input and better touch support. This module is automatically loaded whenever other modules load the "jquery-ui" module.
Implements the location controls, such as the map which can be clicked and the comboboxes for the current location.
Implements the script list and shows the active script.
Implements the object search panel and the quick select buttons.
Implements the time controls, the updateTimeDisplay
method is called repeatedly as an animation by the ui/mainui module.
Implements the FOV slider and the "virtual joystick" for the viewport movement.
Implements the projection, landscape and skyculture lists, and some minor things related to other view options.