diff --git a/README.md b/README.md index 3471660..b11089e 100644 --- a/README.md +++ b/README.md @@ -10,112 +10,32 @@ **Druid** - powerful Defold component UI library. Use basic and extended **Druid** components or make your own game-specific components to make amazing GUI in your games. +## Overview + + + ## Setup ### Dependency -You can use the **Druid** extension in your own project by adding this project as a [Defold library dependency](https://www.defold.com/manuals/libraries/). Open your game.project file and in the dependencies field under project add: +You can use the **Druid** extension in your own project by adding this project as a [Defold library dependency](https://www.defold.com/manuals/libraries/). Open your `game.project` file and in the dependencies field under project add: -> [https://github.com/Insality/druid/archive/master.zip](https://github.com/Insality/druid/archive/master.zip) +**Druid v0.10.3** +> [https://github.com/Insality/druid/archive/refs/tags/0.10.3.zip](https://github.com/Insality/druid/archive/refs/tags/0.10.3.zip) -Or point to the ZIP file of a [specific release](https://github.com/Insality/druid/releases). +Here is a list of [all releases](https://github.com/Insality/druid/releases). -### Input bindings - -**Druid** requires the following input bindings: - -- Mouse trigger - `Button 1` -> `touch` _For basic input components_ -- Mouse trigger - `Wheel up` -> `mouse_wheel_up` _For scroll component_ -- Mouse trigger - `Wheel down` -> `mouse_wheel_down` _For scroll component_ -- Key trigger - `Backspace` -> `key_backspace` _For back_handler component, input component_ -- Key trigger - `Back` -> `key_back` _For back_handler component, Android back button, input component_ -- Key trigger - `Enter` -> `key_enter` _For input component, optional_ -- Key trigger - `Esc` -> `key_esc` _For input component, optional_ -- Touch triggers - `Touch multi` -> `touch_multi` _For scroll component_ - -![](media/input_binding_2.png) -![](media/input_binding_1.png) +### Input Bindings +Druid uses `/builtins/input/all.input_binding` input bindins. For advanced setup see the Input Binding section in Advanced Setup. -### Change key bindings [optional] -If you have to use your own key bindings (and key name), you can change it in your *game.project* file. - -Here is current default values for key bindings: -``` -[druid] -input_text = text -input_touch = touch -input_marked_text = marked_text -input_key_esc = key_esc -input_key_back = key_back -input_key_enter = key_enter -input_key_backspace = key_backspace -input_multitouch = touch_multi -input_scroll_up = mouse_wheel_up -input_scroll_down = mouse_wheel_down -``` - - -### Input capturing [optional] - -By default, **Druid** will auto-capture input focus, if any input component will be created. So you don't need to call `msg.post(".", "acquire_input_focus")` - -If you don't need this behaviour, you can disable it by setting `druid.no_auto_input` field in _game.project_: -``` -[druid] -no_auto_input = 1 -``` - - -### Template name check [optional] - -By default, **Druid** will auto check the parent component template name to build the full template name for component. - -If for some reason you want to pass the full template name by yourself, you can disable it by setting `druid.no_auto_template` field in _game.project_: - -``` -[druid] -no_auto_template = 1 -``` - - -### Stencil check [optional] - -When creating input components inside stencil nodes, **Druid** automatically setup `component:set_click_zone()` on _late_init_ component step to restrict input clicks outside this stencil zone. -To disable this feature add next field in your _game.project_ file -``` -[druid] -no_stencil_check = 1 -``` - - -### Code [optional] - -Adjust **Druid** settings, if needed: -```lua -local druid = require("druid.druid") - --- Used for button component and custom components --- Callback should play sound by name: function(sound_id) ... end -druid.set_sound_function(callback) - --- Used for lang_text component --- Callback should return localized string by locale id: function(locale_id) ... end -druid.set_text_function(callback) - --- Used for change default Druid style -druid.set_default_style(your_style) - --- Call this function on language changing in the game, --- to retranslate all lang_text components: -druid.on_language_change() - --- Call this function inside window.set_listener --- to catch game focus lost/gained callbacks: --- window.set_listener(function(self, event, data) druid.on_window_callback(event, data) end)) -druid.on_window_callback(event) -``` +## Usage +Here only basic usage. +How to read this doc. +Annotations. +Example of advanced usage - different doc. +Example of custom components - different doc. ## Components @@ -123,36 +43,36 @@ Here is full **Druid** components list: ### Basic Components -| Name | Description | API page | Example Link | Preview | -|------|-------------|----------|--------------|---------| -| **[Button](docs_md/01-components.md#button)** | Basic input component. Handles all types of interactions: click, long click, hold click, double click, etc | [Button API](https://insality.github.io/druid/modules/Button.html) | [Button Example](https://insality.github.io/druid/druid/?example=general_buttons) | | -| **[Text](docs_md/01-components.md#text)** | Wrap on GUI text node, handle different text size adjusting, providing additional text API | [Text API](https://insality.github.io/druid/modules/Text.html) | [Text Example](https://insality.github.io/druid/druid/?example=texts_general) | | -| **[Scroll](docs_md/01-components.md#scroll)** | Scroll component | [Scroll API](https://insality.github.io/druid/modules/Scroll.html) | [Scroll Example](https://insality.github.io/druid/druid/?example=general_scroll) | | -| **[Blocker](docs_md/01-components.md#blocker)** | Block user input in node zone area | [Blocker API](https://insality.github.io/druid/modules/Blocker.html) | ❌ | | -| **[Back Handler](docs_md/01-components.md#back-handler)** | Handle back button (Android back button, backspace key) | [Back Handler API](https://insality.github.io/druid/modules/BackHandler.html) | ❌ | | -| **[Static Grid](docs_md/01-components.md#static-grid)** | Component to manage node positions with equal sizes | [Static Grid API](https://insality.github.io/druid/modules/StaticGrid.html) | [Static Gid Example](https://insality.github.io/druid/druid/?example=general_grid) | | -| **[Hover](docs_md/01-components.md#hover)** | Handle hover node state on node | [Hover API](https://insality.github.io/druid/modules/Hover.html) | ❌ | | -| **[Swipe](docs_md/01-components.md#swipe)** | Handle swipe gestures on node | [Swipe API](https://insality.github.io/druid/modules/Swipe.html) | [Swipe Example](https://insality.github.io/druid/druid/?example=general_swipe) | | -| **[Drag](docs_md/01-components.md#drag)** | Handle drag input on node | [Drag API](https://insality.github.io/druid/modules/Drag.html) | [Drag Example](https://insality.github.io/druid/druid/?example=general_drag) | | +| Name | Description | Example |
Preview
| +|------|-------------|---------|---------| +| **[Button](https://insality.github.io/druid/modules/Button.html)** | Basic input component. Handles all types of interactions: click, long click, hold click, double click, etc | [Button Example](https://insality.github.io/druid/druid/?example=general_buttons) | | +| **[Text](https://insality.github.io/druid/modules/Text.html)** | Wrap on GUI text node, handle different text size adjusting, providing additional text API | [Text Example](https://insality.github.io/druid/druid/?example=texts_general) | | +| **[Scroll](https://insality.github.io/druid/modules/Scroll.html)** | Scroll component | [Scroll Example](https://insality.github.io/druid/druid/?example=general_scroll) | | +| **[Blocker](https://insality.github.io/druid/modules/Blocker.html)** | Block user input in node zone area | ❌ | | +| **[Back Handler](https://insality.github.io/druid/modules/BackHandler.html)** | Handle back button (Android back button, backspace key) | ❌ | | +| **[Static Grid](https://insality.github.io/druid/modules/StaticGrid.html)** | Component to manage node positions with equal sizes | [Static Gid Example](https://insality.github.io/druid/druid/?example=general_grid) | | +| **[Hover](https://insality.github.io/druid/modules/Hover.html)** | Handle hover node state on node | ❌ | | +| **[Swipe](https://insality.github.io/druid/modules/Swipe.html)** | Handle swipe gestures on node | [Swipe Example](https://insality.github.io/druid/druid/?example=general_swipe) | | +| **[Drag](https://insality.github.io/druid/modules/Drag.html)** | Handle drag input on node | [Drag Example](https://insality.github.io/druid/druid/?example=general_drag) | | ### Extended components -> Extended components before usage should be registered in **Druid** with `druid.register_component()` function. +> Extended components before usage should be registered in **Druid** with `druid.register()` function. -| Name | Description | API page | Example Link | Preview | -|------|-------------|----------|--------------|---------| -| **[Checkbox](docs_md/01-components.md#checkbox)** | Checkbox component | [Checkbox API](https://insality.github.io/druid/modules/Checkbox.html) | [Checkbox Example](https://insality.github.io/druid/druid/?example=general_checkboxes) | | -| **[Checkbox group](docs_md/01-components.md#checkbox-group)** | Several checkboxes in one group | [Checkbox group API](https://insality.github.io/druid/modules/CheckboxGroup.html) | [Checkbox group Example](https://insality.github.io/druid/druid/?example=general_checkboxes) | | -| **[Radio group](docs_md/01-components.md#radio-group)** | Several checkboxes in one group with a single choice | [Radio group API](https://insality.github.io/druid/modules/RadioGroup.html) | [Radio Group Example](https://insality.github.io/druid/druid/?example=general_checkboxes) | | -| **[Dynamic Grid](docs_md/01-components.md#dynamic-grid)** | Component to manage node positions with different sizes. Only in one row or column | [Dynamic Grid API](https://insality.github.io/druid/modules/DynamicGrid.html) | [Dynamic Grid Example](https://insality.github.io/druid/druid/?example=general_grid) | | -| **[Data List](docs_md/01-components.md#data-list)** | Component to manage data for huge datasets in scroll | [Data List API](https://insality.github.io/druid/modules/DataList.html) | [Data List Example](https://insality.github.io/druid/druid/?example=general_data_list) | | -| **[Input](docs_md/01-components.md#input)** | User text input component | [Input API](https://insality.github.io/druid/modules/Input.html) | [Input Example](https://insality.github.io/druid/druid/?example=general_input) | | -| **[Lang text](docs_md/01-components.md#lang-text)** | Wrap on Text component to handle localization | [Lang Text API](https://insality.github.io/druid/modules/LangText.html) | | -| **[Progress](docs_md/01-components.md#progress)** | Progress bar component | [Progress API](https://insality.github.io/druid/modules/Progress.html) | [Progress Example](https://insality.github.io/druid/druid/?example=general_progress_bar) | | -| **[Slider](docs_md/01-components.md#slider)** | Slider component | [Slider API](https://insality.github.io/druid/modules/Slider.html) | [Slider Example](https://insality.github.io/druid/druid/?example=general_sliders) | | -| **[Timer](docs_md/01-components.md#timer)** | Handle timers on GUI text node | [Timer API](https://insality.github.io/druid/modules/Timer.html) | | -| **[Hotkey](docs_md/01-components.md#hotkey)** | Handle keyboard hotkeys with key modificators | [Hotkey API](https://insality.github.io/druid/modules/Hotkey.html) | [Hotkey Example](https://insality.github.io/druid/druid/?example=general_hokey) | | -| **[Layout](docs_md/01-components.md#layout)** | Handle node size depends on layout mode and screen aspect ratio | [Layout API](https://insality.github.io/druid/modules/Layout.html) | [Layout Example](https://insality.github.io/druid/druid/?example=general_layout) | | +| Name | Description | Example |
Preview
| +|------|-------------|---------|---------| +| **[Checkbox](https://insality.github.io/druid/modules/Checkbox.html)** | Checkbox component | [Checkbox Example](https://insality.github.io/druid/druid/?example=general_checkboxes) | | +| **[Checkbox group](https://insality.github.io/druid/modules/CheckboxGroup.html)** | Several checkboxes in one group | [Checkbox group Example](https://insality.github.io/druid/druid/?example=general_checkboxes) | | +| **[Radio group](https://insality.github.io/druid/modules/RadioGroup.html)** | Several checkboxes in one group with a single choice | [Radio Group Example](https://insality.github.io/druid/druid/?example=general_checkboxes) | | +| **[Dynamic Grid](https://insality.github.io/druid/modules/DynamicGrid.html)** | Component to manage node positions with different sizes. Only in one row or column | [Dynamic Grid Example](https://insality.github.io/druid/druid/?example=general_grid) | | +| **[Data List](https://insality.github.io/druid/modules/DataList.html)** | Component to manage data for huge datasets in scroll | [Data List Example](https://insality.github.io/druid/druid/?example=general_data_list) | | +| **[Input](https://insality.github.io/druid/modules/Input.html)** | User text input component | [Input Example](https://insality.github.io/druid/druid/?example=general_input) | | +| **[Lang text](https://insality.github.io/druid/modules/LangText.html)** | Wrap on Text component to handle localization | ❌ | | +| **[Progress](https://insality.github.io/druid/modules/Progress.html)** | Progress bar component | [Progress Example](https://insality.github.io/druid/druid/?example=general_progress_bar) | | +| **[Slider](https://insality.github.io/druid/modules/Slider.html)** | Slider component | [Slider Example]() | | +| **[Timer](https://insality.github.io/druid/modules/Timer.html)** | Handle timers on GUI text node | ❌ | | +| **[Hotkey](https://insality.github.io/druid/modules/Hotkey.html)** | Handle keyboard hotkeys with key modificators | [Hotkey Example](https://insality.github.io/druid/druid/?example=general_hokey) | | +| **[Layout](https://insality.github.io/druid/modules/Layout.html)** | Handle node size depends on layout mode and screen aspect ratio | [Layout Example](https://insality.github.io/druid/druid/?example=general_layout) | | For a complete overview, see: **_[components.md](docs_md/01-components.md)_**. @@ -182,14 +102,13 @@ function final(self) end function update(self, dt) - self.druid:update(dt) + self.druid:update(dt) end function on_message(self, message_id, message, sender) self.druid:on_message(message_id, message, sender) end - function on_input(self, action_id, action) return self.druid:on_input(action_id, action) end diff --git a/docs/index.html b/docs/index.html index 1b184f4..90342ca 100644 --- a/docs/index.html +++ b/docs/index.html @@ -3,7 +3,7 @@ - Defold Druid UI Library + Defold Druid UI Framework diff --git a/docs_md/advanced-setup.md b/docs_md/advanced-setup.md new file mode 100644 index 0000000..0704e26 --- /dev/null +++ b/docs_md/advanced-setup.md @@ -0,0 +1,94 @@ +## Input bindings + +**Druid** requires the following input bindings: + +- Mouse trigger - `Button 1` -> `touch` _For basic input components_ +- Mouse trigger - `Wheel up` -> `mouse_wheel_up` _For scroll component_ +- Mouse trigger - `Wheel down` -> `mouse_wheel_down` _For scroll component_ +- Key trigger - `Backspace` -> `key_backspace` _For back_handler component, input component_ +- Key trigger - `Back` -> `key_back` _For back_handler component, Android back button, input component_ +- Key trigger - `Enter` -> `key_enter` _For input component, optional_ +- Key trigger - `Esc` -> `key_esc` _For input component, optional_ +- Touch triggers - `Touch multi` -> `touch_multi` _For scroll component_ + +![](media/input_binding_2.png) +![](media/input_binding_1.png) + +## Change key bindings [optional] +If you have to use your own key bindings (and key name), you can change it in your *game.project* file. + +Here is current default values for key bindings: +``` +[druid] +input_text = text +input_touch = touch +input_marked_text = marked_text +input_key_esc = key_esc +input_key_back = key_back +input_key_enter = key_enter +input_key_backspace = key_backspace +input_multitouch = touch_multi +input_scroll_up = mouse_wheel_up +input_scroll_down = mouse_wheel_down +``` + + +## Input capturing [optional] + +By default, **Druid** will auto-capture input focus, if any input component will be created. So you don't need to call `msg.post(".", "acquire_input_focus")` + +If you don't need this behaviour, you can disable it by setting `druid.no_auto_input` field in _game.project_: +``` +[druid] +no_auto_input = 1 +``` + + +## Template name check [optional] + +By default, **Druid** will auto check the parent component template name to build the full template name for component. + +If for some reason you want to pass the full template name by yourself, you can disable it by setting `druid.no_auto_template` field in _game.project_: + +``` +[druid] +no_auto_template = 1 +``` + + +## Stencil check [optional] + +When creating input components inside stencil nodes, **Druid** automatically setup `component:set_click_zone()` on _late_init_ component step to restrict input clicks outside this stencil zone. +To disable this feature add next field in your _game.project_ file +``` +[druid] +no_stencil_check = 1 +``` + + +## Code [optional] + +Adjust **Druid** settings, if needed: +```lua +local druid = require("druid.druid") + +-- Used for button component and custom components +-- Callback should play sound by name: function(sound_id) ... end +druid.set_sound_function(callback) + +-- Used for lang_text component +-- Callback should return localized string by locale id: function(locale_id) ... end +druid.set_text_function(callback) + +-- Used for change default Druid style +druid.set_default_style(your_style) + +-- Call this function on language changing in the game, +-- to retranslate all lang_text components: +druid.on_language_change() + +-- Call this function inside window.set_listener +-- to catch game focus lost/gained callbacks: +-- window.set_listener(function(self, event, data) druid.on_window_callback(event, data) end)) +druid.on_window_callback(event) +``` diff --git a/druid/druid.lua b/druid/druid.lua index 3970fa5..d868a76 100644 --- a/druid/druid.lua +++ b/druid/druid.lua @@ -7,24 +7,26 @@ -- Druid components or make your own game-specific components to make -- amazing GUI in your games. -- --- To start use Druid, check the Basic Usage below. +-- To start using Druid, please refer to the Basic Usage section below. -- -- # Tech Info # -- --- - Each Druid keeps the self context from constructor to pass it into each Druid callback +-- • Each Druid instance maintains the self context from the constructor and passes it to each Druid callback. +-- +-- • There is a system in place to track all Druid instances, so it is required to call druid:final() -- -- See next: @{DruidInstance} -- -- @usage -- local druid = require("druid.druid") -- --- local function button_callback(self) --- print("Button was clicked!") +-- local function on_play(self) +-- print("Gonna play!") -- end -- -- function init(self) -- self.druid = druid.new(self) --- self.druid:new_button("button_node_name", button_callback) +-- self.druid:new_button("button_play", on_play) -- end -- -- function final(self) @@ -67,10 +69,11 @@ local function get_druid_instances() end ---- Register new external Druid component. +--- Register a new external Druid component. -- --- You can register your own components to create it with druid:new_{name} function --- For example, you can register your own component "my_component" and create it with druid:new_my_component(...) +-- You can register your own components by creating them with the druid:new_{name} function. +-- For example, if you want to register a component called "my_component", you can create it using druid:new_my_component(...). +-- This can be useful if you have your own "basic" components that you don't want to re-create each time. -- @function druid.register -- @tparam string name module name -- @tparam table module lua table with component @@ -81,19 +84,18 @@ end -- local druid = druid.new(self) -- local component_instance = self.druid:new_my_component(...) function M.register(name, module) - -- TODO: Find better solution to creating elements? - -- Current way is very implicit druid_instance["new_" .. name] = function(self, ...) return druid_instance.new(self, module, ...) end end ---- Create new Druid instance to create GUI components. +--- Create a new Druid instance for creating GUI components. +-- -- @function druid.new --- @tparam table context Druid context. Usually it is *self* of *gui_script. It passes into all Druid callbacks --- @tparam[opt] table style Druid style table to override style params for this Druid instance --- @treturn druid_instance Druid instance @{DruidInstance} +-- @tparam table context The Druid context. Usually, this is the self of the gui_script. It is passed into all Druid callbacks. +-- @tparam[opt] table style The Druid style table to override style parameters for this Druid instance. +-- @treturn druid_instance The Druid instance @{DruidInstance}. -- @usage -- local druid = require("druid.druid") -- @@ -113,8 +115,8 @@ end --- Set your own default style for all Druid instances. -- --- To create your own style file, copy the default style file and change it. --- Register new style before your Druid instances creation. +-- To create your own style file, copy the default style file and make changes to it. +-- Register the new style before creating your Druid instances. -- @function druid.set_default_style -- @tparam table style Druid style module -- @usage @@ -125,10 +127,10 @@ function M.set_default_style(style) end ---- Set text function for LangText component. +--- Set the text function for the LangText component. -- --- Druid locale component will call this function to get translated text. After set_text_funtion --- all existing locale component will be updated +-- The Druid locale component will call this function to get translated text. +-- After setting the text function, all existing locale components will be updated. -- @function druid.set_text_function -- @tparam function callback Get localized text function -- @usage @@ -141,10 +143,10 @@ function M.set_text_function(callback) end ---- Set Druid sound function to play UI sounds if used. +--- Set the Druid sound function to play UI sounds if used. -- --- Set function to play sound by sound_id. It used in Button click and play "click" sound. --- Also can be used by play sound in your custom components (see default Druid style file for example) +-- Set a function to play a sound given a sound_id. This function is used for button clicks to play the "click" sound. +-- It can also be used to play sounds in your custom components (see the default Druid style file for an example). -- @function druid.set_sound_function -- @tparam function callback Sound play callback -- @usage @@ -156,9 +158,9 @@ function M.set_sound_function(callback) end ---- Set window callback to enable *on_focus_gain* and *on_focus_lost* functions. +--- Set the window callback to enable on_focus_gain and on_focus_lost functions. -- --- Used to trigger on_focus_lost and on_focus_gain in Druid components +-- This is used to trigger the on_focus_lost and on_focus_gain functions in Druid components. -- @function druid.on_window_callback -- @tparam string event Event param from window listener -- @usage @@ -188,9 +190,9 @@ function M.on_window_callback(event) end ---- Call this on game language change. +--- Call this function when the game language changes. -- --- This function will update all LangText components +-- This function will translate all current LangText components. -- @function druid.on_language_change -- @usage -- druid.on_language_change() diff --git a/druid/system/druid_instance.lua b/druid/system/druid_instance.lua index e8aefb6..9942f2f 100755 --- a/druid/system/druid_instance.lua +++ b/druid/system/druid_instance.lua @@ -4,30 +4,30 @@ -- -- # Component List # -- --- See all component list in "See Also" section. +-- For a list of all available components, please refer to the "See Also" section. -- -- # Notes # -- --- Take a look on the next API pages: +-- Please review the following API pages: -- --- - @{Helper} - Useful pack of functions to work with GUI nodes like centrate nodes +-- @{Helper} - A useful set of functions for working with GUI nodes, such as centering nodes, get GUI scale ratio, etc -- --- - @{DruidEvent} - The core event system in Druid. See how to subscribe on any event +-- @{DruidEvent} - The core event system in Druid. Learn how to subscribe to any event in every Druid component. -- --- - @{BaseComponent} - the parent of all Druid components, you can see all default component methods there +-- @{BaseComponent} - The parent class of all Druid components. You can find all default component methods there. -- --- Other things: +-- Other important information: -- --- - To use Druid, first you should create a Druid instance to spawn components and add Druids main engine functions: update, final, on_message and on_input. +-- • To use Druid, you need to create a Druid instance first. This instance is used to spawn components. -- --- - All Druid components take node name string as arguments, don't do gui.get_node() before. +-- • When using Druid components, provide the node name as a string argument directly. Avoid calling gui.get_node() before passing it to the component. Because Druid can get nodes from template and cloned gui nodes. -- --- - All Druid and component methods are called with : like self.druid:new_button(). +-- • All Druid and component methods are called using the colon operator (e.g., self.druid:new_button()). -- @usage -- local druid = require("druid.druid") -- -- local function close_window(self) --- print("WOW, you closed the game!") +-- print("Yeah! You closed the game!") -- end -- -- function init(self) @@ -71,49 +71,57 @@ local settings = require("druid.system.settings") local base_component = require("druid.component") local druid_input = require("druid.helper.druid_input") -local back_handler = require("druid.base.back_handler") -local blocker = require("druid.base.blocker") -local button = require("druid.base.button") local drag = require("druid.base.drag") +local text = require("druid.base.text") local hover = require("druid.base.hover") local scroll = require("druid.base.scroll") +local button = require("druid.base.button") +local blocker = require("druid.base.blocker") local static_grid = require("druid.base.static_grid") -local text = require("druid.base.text") +local back_handler = require("druid.base.back_handler") -- To use this components, you should register them first --- local checkbox = require("druid.extended.checkbox") --- local checkbox_group = require("druid.extended.checkbox_group") --- local dynamic_grid = require("druid.extended.dynamic_grid") -- local input = require("druid.extended.input") --- local lang_text = require("druid.extended.lang_text") --- local progress = require("druid.extended.progress") --- local radio_group = require("druid.extended.radio_group") --- local slider = require("druid.extended.slider") --- local timer_component = require("druid.extended.timer") --- local data_list = require("druid.extended.data_list") -- local swipe = require("druid.extended.swipe") +-- local slider = require("druid.extended.slider") +-- local checkbox = require("druid.extended.checkbox") +-- local progress = require("druid.extended.progress") +-- local data_list = require("druid.extended.data_list") +-- local lang_text = require("druid.extended.lang_text") +-- local timer_component = require("druid.extended.timer") +-- local radio_group = require("druid.extended.radio_group") +-- local dynamic_grid = require("druid.extended.dynamic_grid") +-- local checkbox_group = require("druid.extended.checkbox_group") local DruidInstance = class("druid.druid_instance") local IS_NO_AUTO_INPUT = sys.get_config_int("druid.no_auto_input", 0) == 1 -local function input_init(self) - if IS_NO_AUTO_INPUT or self.input_inited then +local function set_input_state(self, is_input_inited) + if IS_NO_AUTO_INPUT or (self.input_inited == is_input_inited) then return end - self.input_inited = true - druid_input.focus() + self.input_inited = is_input_inited + if is_input_inited then + druid_input.focus() + else + druid_input.remove() + end end -local function input_release(self) - if IS_NO_AUTO_INPUT or not self.input_inited then - return +-- a and b - two Druid components +-- @local +local function sort_input_comparator(a, b) + local a_priority = a:get_input_priority() + local b_priority = b:get_input_priority() + + if a_priority ~= b_priority then + return a_priority < b_priority end - self.input_inited = false - druid_input.remove() + return a:get_uid() < b:get_uid() end @@ -123,17 +131,11 @@ local function sort_input_stack(self) return end - table.sort(input_components, function(a, b) - if a:get_input_priority() ~= b:get_input_priority() then - return a:get_input_priority() < b:get_input_priority() - end - - return a:get_uid() < b:get_uid() - end) + table.sort(input_components, sort_input_comparator) end --- Create the component itself +-- Create the Druid component instance local function create(self, instance_class) local instance = instance_class() instance:setup_component(self, self._context, self._style, instance_class) @@ -150,6 +152,7 @@ local function create(self, instance_class) end +-- Before processing any input check if we need to update input stack local function check_sort_input_stack(self, components) if not components or #components == 0 then return @@ -177,19 +180,11 @@ local function can_use_input_component(self, component) local can_by_blacklist = true if self._input_whitelist and #self._input_whitelist > 0 then - if helper.contains(self._input_whitelist, component) then - can_by_whitelist = true - else - can_by_whitelist = false - end + can_by_whitelist = not not helper.contains(self._input_whitelist, component) end if self._input_blacklist and #self._input_blacklist > 0 then - if helper.contains(self._input_blacklist, component) then - can_by_blacklist = false - else - can_by_blacklist = true - end + can_by_blacklist = not helper.contains(self._input_blacklist, component) end return can_by_blacklist and can_by_whitelist @@ -200,7 +195,7 @@ local function process_input(self, action_id, action, components) local is_input_consumed = false if #components == 0 then - return is_input_consumed + return false end for i = #components, 1, -1 do @@ -250,27 +245,15 @@ function DruidInstance.initialize(self, context, style) self._input_blacklist = nil self._input_whitelist = nil - self.components_interest = {} self.components_all = {} + self.components_interest = {} for i = 1, #base_component.ALL_INTERESTS do self.components_interest[base_component.ALL_INTERESTS[i]] = {} end end ---- Create new druid component --- @tparam DruidInstance self --- @tparam Component component Component module --- @tparam args ... Other component params to pass it to component:init function --- @local -function DruidInstance.create(self, component, ...) - helper.deprecated("The druid:create is deprecated. Please use druid:new instead") - - return DruidInstance.new(self, component, ...) -end - - ---- Create new druid component +--- Create new component -- @tparam DruidInstance self -- @tparam Component component Component module -- @tparam args ... Other component params to pass it to component:init function @@ -302,7 +285,7 @@ function DruidInstance.final(self) self._deleted = true - input_release(self) + set_input_state(self, false) end @@ -324,8 +307,8 @@ function DruidInstance.remove(self, component) if parent then parent:__remove_children(children[i]) end + children[i] = nil end - component._meta.children = {} local all_components = self.components_all for i = #all_components, 1, -1 do @@ -350,8 +333,11 @@ function DruidInstance.remove(self, component) end ---- Druid late update function call after init and before update step +--- Druid late update function called after initialization and before the regular update step +-- This function is used to check the GUI state and perform actions after all components and nodes have been created. +-- An example use case is performing an auto stencil check in the GUI hierarchy for input components. -- @tparam DruidInstance self +-- @local function DruidInstance.late_init(self) local late_init_components = self.components_interest[base_component.ON_LATE_INIT] while late_init_components[1] do @@ -361,27 +347,30 @@ function DruidInstance.late_init(self) if not self.input_inited and #self.components_interest[base_component.ON_INPUT] > 0 then -- Input init on late init step, to be sure it goes after user go acquire input - input_init(self) + set_input_state(self, true) end end ---- Druid update function +--- Call this in gui_script update function. +-- Used for: scroll, progress, timer components -- @tparam DruidInstance self -- @tparam number dt Delta time function DruidInstance.update(self, dt) self._is_late_remove_enabled = true + local components = self.components_interest[base_component.ON_UPDATE] for i = 1, #components do components[i]:update(dt) end - self._is_late_remove_enabled = false + self._is_late_remove_enabled = false self:_clear_late_remove() end ---- Druid on_input function +--- Call this in gui_script on_input function. +-- Used for almost all components -- @tparam DruidInstance self -- @tparam hash action_id Action_id from on_input -- @tparam table action Action from on_input @@ -394,23 +383,23 @@ function DruidInstance.on_input(self, action_id, action) local is_input_consumed = process_input(self, action_id, action, components) self._is_late_remove_enabled = false - self:_clear_late_remove() + return is_input_consumed end ---- Druid on_message function +--- Call this in gui_script on_message function. +-- Used for special actions. See SPECIFIC_UI_MESSAGES table -- @tparam DruidInstance self -- @tparam hash message_id Message_id from on_message -- @tparam table message Message from on_message -- @tparam hash sender Sender from on_message function DruidInstance.on_message(self, message_id, message, sender) - -- TODO: refactor for more juicy code local specific_ui_message = base_component.SPECIFIC_UI_MESSAGES[message_id] - local on_message_input_message = base_component.ON_MESSAGE_INPUT - if specific_ui_message == on_message_input_message then + if specific_ui_message == base_component.ON_MESSAGE_INPUT then + -- ON_MESSAGE_INPUT is special message, need to perform additional logic local components = self.components_interest[base_component.ON_MESSAGE_INPUT] if components then for i = 1, #components do @@ -421,6 +410,7 @@ function DruidInstance.on_message(self, message_id, message, sender) end end elseif specific_ui_message then + -- Resend special message to all components with the related interest local components = self.components_interest[specific_ui_message] if components then for i = 1, #components do @@ -429,6 +419,7 @@ function DruidInstance.on_message(self, message_id, message, sender) end end else + -- Resend message to all components with on_message interest local components = self.components_interest[base_component.ON_MESSAGE] for i = 1, #components do components[i]:on_message(message_id, message, sender) @@ -437,7 +428,7 @@ function DruidInstance.on_message(self, message_id, message, sender) end ---- Druid on focus lost interest function. +--- Calls the on_focus_lost function in all related components -- This one called by on_window_callback by global window listener -- @tparam DruidInstance self -- @local @@ -449,7 +440,7 @@ function DruidInstance.on_focus_lost(self) end ---- Druid on focus gained interest function. +--- Calls the on_focus_gained function in all related components -- This one called by on_window_callback by global window listener -- @tparam DruidInstance self -- @local @@ -461,7 +452,7 @@ function DruidInstance.on_focus_gained(self) end ---- Druid on language change. +--- Calls the on_language_change function in all related components -- This one called by global druid.on_language_change, but can be -- call manualy to update all translations -- @tparam DruidInstance self @@ -475,6 +466,7 @@ end --- Set whitelist components for input processing. +-- -- If whitelist is not empty and component not contains in this list, -- component will be not processed on input step -- @tparam DruidInstance self @@ -497,6 +489,7 @@ end --- Set blacklist components for input processing. +-- -- If blacklist is not empty and component contains in this list, -- component will be not processed on input step -- @tparam DruidInstance self @{DruidInstance} @@ -522,6 +515,7 @@ end -- @tparam DruidInstance self @{DruidInstance} -- @tparam bool is_debug -- @treturn self @{DruidInstance} +-- @local function DruidInstance.set_debug(self, is_debug) self._is_debug = is_debug return self @@ -532,10 +526,12 @@ end -- @tparam DruidInstance self @{DruidInstance} -- @tparam string message -- @tparam[opt] table context +-- @local function DruidInstance.log_message(self, message, context) if not self._is_debug then return end + print("[Druid]:", message, helper.table_to_string(context)) end @@ -544,246 +540,250 @@ end -- @tparam DruidInstance self @{DruidInstance} -- @local function DruidInstance._clear_late_remove(self) - if #self._late_remove > 0 then - for i = 1, #self._late_remove do - self:remove(self._late_remove[i]) - end - self._late_remove = {} + if #self._late_remove == 0 then + return end + + for i = 1, #self._late_remove do + self:remove(self._late_remove[i]) + end + self._late_remove = {} end ---- Create button basic component + +--- Create @{Button} component -- @tparam DruidInstance self --- @tparam node node Gui node +-- @tparam node node GUI node -- @tparam function callback Button callback -- @tparam[opt] table params Button callback params -- @tparam[opt] node anim_node Button anim node (node, if not provided) --- @treturn Button button component +-- @treturn Button @{Button} component function DruidInstance.new_button(self, node, callback, params, anim_node) return DruidInstance.new(self, button, node, callback, params, anim_node) end ---- Create blocker basic component +--- Create @{Blocker} component -- @tparam DruidInstance self -- @tparam node node Gui node --- @treturn Blocker blocker component +-- @treturn Blocker @{Blocker} component function DruidInstance.new_blocker(self, node) return DruidInstance.new(self, blocker, node) end ---- Create back_handler basic component +--- Create @{BackHandler} component -- @tparam DruidInstance self -- @tparam callback callback On back button -- @tparam[opt] any params Callback argument --- @treturn BackHandler back_handler component +-- @treturn BackHandler @{BackHandler} component function DruidInstance.new_back_handler(self, callback, params) return DruidInstance.new(self, back_handler, callback, params) end ---- Create hover basic component +--- Create @{Hover} component -- @tparam DruidInstance self -- @tparam node node Gui node -- @tparam function on_hover_callback Hover callback --- @treturn Hover hover component +-- @treturn Hover @{Hover} component function DruidInstance.new_hover(self, node, on_hover_callback) return DruidInstance.new(self, hover, node, on_hover_callback) end ---- Create text basic component +--- Create @{Text} component -- @tparam DruidInstance self -- @tparam node node Gui text node -- @tparam[opt] string value Initial text. Default value is node text from GUI scene. -- @tparam[opt] bool no_adjust If true, text will be not auto-adjust size --- @treturn Text text component +-- @treturn Text @{Text} component function DruidInstance.new_text(self, node, value, no_adjust) return DruidInstance.new(self, text, node, value, no_adjust) end ---- Create grid basic component +--- Create @{StaticGrid} component -- Deprecated -- @tparam DruidInstance self -- @tparam node parent The gui node parent, where items will be placed -- @tparam node element Element prefab. Need to get it size -- @tparam[opt=1] number in_row How many nodes in row can be placed --- @treturn StaticGrid grid component +-- @treturn StaticGrid @{StaticGrid} component +-- @local function DruidInstance.new_grid(self, parent, element, in_row) helper.deprecated("The druid:new_grid is deprecated. Please use druid:new_static_grid instead") return DruidInstance.new(self, static_grid, parent, element, in_row) end ---- Create static grid basic component +--- Create @{StaticGrid} component -- @tparam DruidInstance self -- @tparam node parent The gui node parent, where items will be placed -- @tparam node element Element prefab. Need to get it size -- @tparam[opt=1] number in_row How many nodes in row can be placed --- @treturn StaticGrid grid component +-- @treturn StaticGrid @{StaticGrid} component function DruidInstance.new_static_grid(self, parent, element, in_row) return DruidInstance.new(self, static_grid, parent, element, in_row) end ---- Create scroll basic component +--- Create @{Scroll} component -- @tparam DruidInstance self -- @tparam node view_node GUI view scroll node -- @tparam node content_node GUI content scroll node --- @treturn Scroll scroll component +-- @treturn Scroll @{Scroll} component function DruidInstance.new_scroll(self, view_node, content_node) return DruidInstance.new(self, scroll, view_node, content_node) end ---- Create drag basic component +--- Create @{Drag} component -- @tparam DruidInstance self -- @tparam node node GUI node to detect dragging -- @tparam function on_drag_callback Callback for on_drag_event(self, dx, dy) --- @treturn Drag drag component +-- @treturn Drag @{Drag} component function DruidInstance.new_drag(self, node, on_drag_callback) return DruidInstance.new(self, drag, node, on_drag_callback) end ---- Create swipe basic component +--- Create @{Swipe} component -- @tparam DruidInstance self -- @tparam node node Gui node -- @tparam function on_swipe_callback Swipe callback for on_swipe_end event --- @treturn Swipe swipe component +-- @treturn Swipe @{Swipe} component function DruidInstance.new_swipe(self, node, on_swipe_callback) return helper.extended_component("swipe") end ---- Create dynamic grid component +--- Create @{DynamicGrid} component -- @tparam DruidInstance self -- @tparam node parent The gui node parent, where items will be placed --- @treturn DynamicGrid grid component +-- @treturn DynamicGrid @{DynamicGrid} component function DruidInstance.new_dynamic_grid(self, parent) return helper.extended_component("dynamic_grid") end ---- Create lang_text component +--- Create @{LangText} component -- @tparam DruidInstance self -- @tparam node node The text node -- @tparam string locale_id Default locale id -- @tparam bool no_adjust If true, will not correct text size --- @treturn LangText lang_text component +-- @treturn LangText @{LangText} component function DruidInstance.new_lang_text(self, node, locale_id, no_adjust) return helper.extended_component("lang_text") end ---- Create slider component +--- Create @{Slider} component -- @tparam DruidInstance self -- @tparam node node Gui pin node -- @tparam vector3 end_pos The end position of slider -- @tparam[opt] function callback On slider change callback --- @treturn Slider slider component +-- @treturn Slider @{Slider} component function DruidInstance.new_slider(self, node, end_pos, callback) return helper.extended_component("slider") end ---- Create checkbox component +--- Create @{Checkbox} component -- @tparam DruidInstance self -- @tparam node node Gui node -- @tparam function callback Checkbox callback -- @tparam[opt=node] node click_node Trigger node, by default equals to node -- @tparam[opt=false] boolean initial_state The initial state of checkbox, default - false --- @treturn Checkbox checkbox component +-- @treturn Checkbox @{Checkbox} component function DruidInstance.new_checkbox(self, node, callback, click_node, initial_state) return helper.extended_component("checkbox") end ---- Create input component +--- Create @{Input} component -- @tparam DruidInstance self -- @tparam node click_node Button node to enabled input component -- @tparam node text_node Text node what will be changed on user input -- @tparam[opt] number keyboard_type Gui keyboard type for input field --- @treturn Input input component +-- @treturn Input @{Input} component function DruidInstance.new_input(self, click_node, text_node, keyboard_type) return helper.extended_component("input") end ---- Create checkbox_group component +--- Create @{CheckboxGroup} component -- @tparam DruidInstance self -- @tparam node[] nodes Array of gui node -- @tparam function callback Checkbox callback -- @tparam[opt=node] node[] click_nodes Array of trigger nodes, by default equals to nodes --- @treturn CheckboxGroup checkbox_group component +-- @treturn CheckboxGroup @{CheckboxGroup} component function DruidInstance.new_checkbox_group(self, nodes, callback, click_nodes) return helper.extended_component("checkbox_group") end ---- Create data list basic component +--- Create @{DataList} component -- @tparam DruidInstance self -- @tparam Scroll druid_scroll The Scroll instance for Data List component -- @tparam Grid druid_grid The Grid instance for Data List component -- @tparam function create_function The create function callback(self, data, index, data_list). Function should return (node, [component]) --- @treturn DataList data_list component +-- @treturn DataList @{DataList} component function DruidInstance.new_data_list(self, druid_scroll, druid_grid, create_function) return helper.extended_component("data_list") end ---- Create radio_group component +--- Create @{RadioGroup} component -- @tparam DruidInstance self -- @tparam node[] nodes Array of gui node -- @tparam function callback Radio callback -- @tparam[opt=node] node[] click_nodes Array of trigger nodes, by default equals to nodes --- @treturn RadioGroup radio_group component +-- @treturn RadioGroup @{RadioGroup} component function DruidInstance.new_radio_group(self, nodes, callback, click_nodes) return helper.extended_component("radio_group") end ---- Create timer component +--- Create @{Timer} component -- @tparam DruidInstance self -- @tparam node node Gui text node -- @tparam number seconds_from Start timer value in seconds -- @tparam[opt=0] number seconds_to End timer value in seconds -- @tparam[opt] function callback Function on timer end --- @treturn Timer timer component +-- @treturn Timer @{Timer} component function DruidInstance.new_timer(self, node, seconds_from, seconds_to, callback) return helper.extended_component("timer") end ---- Create progress component +--- Create @{Progress} component -- @tparam DruidInstance self -- @tparam string|node node Progress bar fill node or node name -- @tparam string key Progress bar direction: const.SIDE.X or const.SIDE.Y -- @tparam[opt=1] number init_value Initial value of progress bar --- @treturn Progress progress component +-- @treturn Progress @{Progress} component function DruidInstance.new_progress(self, node, key, init_value) return helper.extended_component("progress") end ---- Create layout component +--- Create @{Layout} component -- @tparam DruidInstance self -- @tparam string|node node Layout node -- @tparam string mode The layout mode --- @treturn Layout layout component +-- @treturn Layout @{Layout} component function DruidInstance.new_layout(self, node, mode) return helper.extended_component("layout") end ---- Create hotkey component +--- Create @{Hotkey} component -- @tparam DruidInstance self -- @tparam string|string[] keys_array Keys for trigger action. Should contains one action key and any amount of modificator keys -- @tparam function callback Button callback -- @tparam[opt] value params Button callback params --- @treturn Hotkey hotkey component +-- @treturn Hotkey @{Hotkey} component function DruidInstance.new_hotkey(self, keys_array, callback, params) return helper.extended_component("hotkey") end diff --git a/update_docs.sh b/update_docs.sh index 2331abc..34ca68d 100755 --- a/update_docs.sh +++ b/update_docs.sh @@ -13,3 +13,4 @@ echo "Update EmmyLua annotations" original_path=$(pwd) bash $emmylua_generator_path/export.sh $original_path mv $emmylua_generator_path/annotations.lua $original_path/druid/annotations.lua +cp $original_path/utils/ldoc_fixed.css $original_path/docs/ldoc_fixed.css diff --git a/utils/ldoc_fixed.css b/utils/ldoc_fixed.css new file mode 100644 index 0000000..e63d191 --- /dev/null +++ b/utils/ldoc_fixed.css @@ -0,0 +1,311 @@ +/* BEGIN RESET + +Copyright (c) 2010, Yahoo! Inc. All rights reserved. +Code licensed under the BSD License: +http://developer.yahoo.com/yui/license.html +version: 2.8.2r1 +*/ +html { + color: #000; + background: #FFF; +} +body,div,dl,dt,dd,ul,ol,li,h1,h2,h3,h4,h5,h6,pre,code,form,fieldset,legend,input,button,textarea,p,blockquote,th,td { + margin: 0; + padding: 0; +} +table { + border-collapse: collapse; + border-spacing: 0; +} +fieldset,img { + border: 0; +} +address,caption,cite,code,dfn,em,strong,th,var,optgroup { + font-style: inherit; + font-weight: inherit; +} +del,ins { + text-decoration: none; +} +li { + margin-left: 20px; +} +caption,th { + text-align: left; +} +h1,h2,h3,h4,h5,h6 { + font-size: 100%; + font-weight: bold; +} +q:before,q:after { + content: ''; +} +abbr,acronym { + border: 0; + font-variant: normal; +} +sup { + vertical-align: baseline; +} +sub { + vertical-align: baseline; +} +legend { + color: #000; +} +input,button,textarea,select,optgroup,option { + font-family: inherit; + font-size: inherit; + font-style: inherit; + font-weight: inherit; +} +input,button,textarea,select {*font-size:100%; +} +/* END RESET */ + +body { + margin-left: 1em; + margin-right: 1em; + font-family: arial, helvetica, geneva, sans-serif; + background-color: #ffffff; margin: 0px; +} + +code, tt { font-family: monospace; font-size: 1.1em; } +span.parameter { font-family:monospace; } +span.parameter:after { content:":"; } +span.types:before { content:"("; } +span.types:after { content:")"; } +.type { font-weight: bold; font-style:italic } + +body, p, td, th { font-size: .95em; line-height: 1.2em;} + +p, ul { margin: 10px 0 0 0px;} + +strong { font-weight: bold;} + +em { font-style: italic;} + +h1 { + font-size: 1.5em; + margin: 0 0 20px 0; +} +h2, h3, h4 { margin: 15px 0 10px 0; } +h2 { font-size: 1.25em; } +h3 { font-size: 1.15em; } +h4 { font-size: 1.06em; } + +a:link { font-weight: bold; color: #004080; text-decoration: none; } +a:visited { font-weight: bold; color: #006699; text-decoration: none; } +a:link:hover { text-decoration: underline; } + +hr { + color:#cccccc; + background: #00007f; + height: 1px; +} + +blockquote { margin-left: 3em; } + +ul { list-style-type: disc; } + +p.name { + font-family: "Andale Mono", monospace; + padding-top: 1em; +} + +pre { + background-color: rgb(245, 245, 245); + border: 1px solid #C0C0C0; /* silver */ + padding: 10px; + margin: 10px 0 10px 0; + overflow: auto; + font-family: "Andale Mono", monospace; +} + +pre.example { + font-size: .85em; +} + +table.index { border: 1px #00007f; } +table.index td { text-align: left; vertical-align: top; } + +#container { + margin-left: 1em; + margin-right: 1em; + background-color: #ffffff; +} + +#product { + text-align: center; + border-bottom: 1px solid #cccccc; + background-color: #ffffff; +} + +#product big { + font-size: 2em; +} + +#main { + background-color:#FFFFFF; // #f0f0f0; + border-left: 1px solid #cccccc; +} + +#navigation { + position: fixed; + top: 0; + left: 0; + float: left; + width: 14em; + vertical-align: top; + background-color:#FFFFFF; // #f0f0f0; + border-right: 2px solid #cccccc; + overflow: visible; + overflow-y: scroll; + height: 100%; + padding-left: 1em; +} + +#navigation h2 { + background-color:#FFFFFF;//:#e7e7e7; + font-size:1.1em; + color:#000000; + text-align: left; + padding:0.2em; + border-bottom:1px solid #dddddd; +} + +#navigation ul +{ + font-size:1em; + list-style-type: none; + margin: 1px 1px 10px 1px; +} + +#navigation li { + text-indent: -1em; + display: block; + margin: 3px 0px 0px 22px; +} + +#navigation li li a { + margin: 0px 3px 0px -1em; +} + +#content { + margin-left: 14em; + padding: 1em; + padding-left: 2em; + width: 900px; + border-left: 2px solid #cccccc; + // border-right: 2px solid #cccccc; + background-color: #ffffff; +} + +#about { + clear: both; + padding-left: 1em; + margin-left: 14em; // avoid the damn sidebar! + border-top: 2px solid #cccccc; + border-left: 2px solid #cccccc; + background-color: #ffffff; +} + +@media print { + body { + font: 12pt "Times New Roman", "TimeNR", Times, serif; + } + a { font-weight: bold; color: #004080; text-decoration: underline; } + + #main { + background-color: #ffffff; + border-left: 0px; + } + + #container { + margin-left: 2%; + margin-right: 2%; + background-color: #ffffff; + } + + #content { + padding: 1em; + background-color: #ffffff; + } + + #navigation { + display: none; + } + pre.example { + font-family: "Andale Mono", monospace; + font-size: 10pt; + page-break-inside: avoid; + } +} + +table.module_list { + border-width: 1px; + border-style: solid; + border-color: #cccccc; + border-collapse: collapse; +} +table.module_list td { + border-width: 1px; + padding: 3px; + border-style: solid; + border-color: #cccccc; +} +table.module_list td.name { background-color: #f0f0f0; ; min-width: 200px; } +table.module_list td.summary { width: 100%; } + +table.function_list { + border-width: 1px; + border-style: solid; + border-color: #cccccc; + border-collapse: collapse; +} +table.function_list td { + border-width: 1px; + padding: 3px; + border-style: solid; + border-color: #cccccc; +} +table.function_list td.name { background-color: #f6f6ff; ; min-width: 200px; } +table.function_list td.summary { width: 100%; } + +dl.table dt, dl.function dt {border-top: 1px solid #ccc; padding-top: 1em;} +dl.table dd, dl.function dd {padding-bottom: 1em; margin: 10px 0 0 20px;} +dl.table h3, dl.function h3 {font-size: .95em;} + +ul.nowrap { + overflow:auto; + whitespace:nowrap; +} + +/* stop sublists from having initial vertical space */ +ul ul { margin-top: 0px; } +ol ul { margin-top: 0px; } +ol ol { margin-top: 0px; } +ul ol { margin-top: 0px; } + +/* make the target distinct; helps when we're navigating to a function */ +a:target + * { + background-color: #FF9; +} + + +/* styles for prettification of source */ +pre .comment { color: #558817; } +pre .constant { color: #a8660d; } +pre .escape { color: #844631; } +pre .keyword { color: #aa5050; font-weight: bold; } +pre .library { color: #0e7c6b; } +pre .marker { color: #512b1e; background: #fedc56; font-weight: bold; } +pre .string { color: #8080ff; } +pre .number { color: #f8660d; } +pre .operator { color: #2239a8; font-weight: bold; } +pre .preprocessor, pre .prepro { color: #a33243; } +pre .global { color: #800080; } +pre .user-keyword { color: #800080; } +pre .prompt { color: #558817; } +pre .url { color: #272fc2; text-decoration: underline; } +