guiAPI.h 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255
  1. 
  2. // zlib open source license
  3. //
  4. // Copyright (c) 2019 David Forsgren Piuva
  5. //
  6. // This software is provided 'as-is', without any express or implied
  7. // warranty. In no event will the authors be held liable for any damages
  8. // arising from the use of this software.
  9. //
  10. // Permission is granted to anyone to use this software for any purpose,
  11. // including commercial applications, and to alter it and redistribute it
  12. // freely, subject to the following restrictions:
  13. //
  14. // 1. The origin of this software must not be misrepresented; you must not
  15. // claim that you wrote the original software. If you use this software
  16. // in a product, an acknowledgment in the product documentation would be
  17. // appreciated but is not required.
  18. //
  19. // 2. Altered source versions must be plainly marked as such, and must not be
  20. // misrepresented as being the original software.
  21. //
  22. // 3. This notice may not be removed or altered from any source
  23. // distribution.
  24. #ifndef DFPSR_API_GUI
  25. #define DFPSR_API_GUI
  26. #include "types.h"
  27. #include "../api/stringAPI.h"
  28. #include "../gui/InputEvent.h"
  29. // createBackendWindow should be implemented outside of the core framework
  30. // Choose one of the window backends in SDK/native to compile and link with your application.
  31. // std::shared_ptr<dsr::BackendWindow> createBackendWindow(const dsr::String& title, int width, int height);
  32. // Constness on handles doesn't propagate to any inner types
  33. // "const Comopnent&" only means that the writable Component handle can be created from a sub-expression
  34. // because the location where the handle is stored cannot be overwritten.
  35. // This allow getting a component by name and using it as an argument without being stored in a variable.
  36. namespace dsr {
  37. // Window Construction
  38. // A portable window will be wrapped around a native window backend supplied from a call to createBackendWindow.
  39. Window window_create(const dsr::String& title, int32_t width, int32_t height);
  40. Window window_create_fullscreen(const dsr::String& title);
  41. // Returns true iff the window exists
  42. bool window_exists(const Window& window);
  43. // Layout files
  44. // Loading an interface by parsing a layout file's content.
  45. // Raises an exception if window doesn't exist.
  46. void window_loadInterfaceFromString(const Window& window, const dsr::String& content);
  47. // Loading an interface by parsing a layout file loaded by filename.
  48. // Raises an exception if window doesn't exist.
  49. void window_loadInterfaceFromFile(const Window& window, const dsr::ReadableString& filename);
  50. // Store the interface back into a layout file.
  51. // Raises an exception if window doesn't exist.
  52. String window_saveInterfaceToString(const Window& window);
  53. // Find a component
  54. // Get the component being stored directly in the window
  55. // Raises an exception if window doesn't exist.
  56. // There should always exist a root component where more components can be added recursively
  57. Component window_getRoot(const Window& window);
  58. // TODO: Document
  59. // Raises an exception if window doesn't exist.
  60. Component window_findComponentByName(const Window& window, const ReadableString& name, bool mustExist = true);
  61. // TODO: Document
  62. // Raises an exception if window doesn't exist.
  63. Component window_findComponentByNameAndIndex(const Window& window, const ReadableString& name, int index, bool mustExist = true);
  64. // The three main events to run in a loop at the end of the main function
  65. // If the window's event queue contained any resize of the window, the canvas and the depth buffer will be replaced during this call.
  66. // New calls to window_getCanvas and window_getDepthBuffer are required after this call, because the window could be given a new size.
  67. // Returns true iff any event were processed.
  68. // By calling window_executeEvents in a loop while returning false, one can wait for input.
  69. // Sleeping for 10 milliseconds is quite responsive while saving lots of battery.
  70. // Only redrawing the regions that has changed (dirty rectangles et cetera) can further save power.
  71. // Example:
  72. // while (!window_executeEvents(window)) {
  73. // time_sleepSeconds(0.01);
  74. // }
  75. // window_drawComponents(window);
  76. // window_showCanvas(window);
  77. bool window_executeEvents(const Window& window);
  78. // Draw the root component and its children to the canvas.
  79. // Raises an exception if window doesn't exist.
  80. void window_drawComponents(const Window& window);
  81. // Show the canvas.
  82. // Raises an exception if window doesn't exist.
  83. void window_showCanvas(const Window& window);
  84. // Pixel upscaling
  85. // The pixel-scale is the width and height of each canvas pixel when displayed on the window.
  86. // The color and depth buffers from window_getCanvas and window_getDepthBuffer will shrink to fit each pixel within the window.
  87. // Partial pixels at right and bottom sides are replaced with black padding,
  88. // so that mouse coordinates can be divided and multiplied evenly during scale conversion.
  89. // If using a higher value than the default 1, upscaling will be done during the call to window_showCanvas.
  90. // The backend window will receive the upscaled image to display over the whole window.
  91. // Gets the current pixel scale.
  92. // Raises an exception if window doesn't exist.
  93. int window_getPixelScale(const Window& window);
  94. // Assigns a new pixel scale.
  95. // Raises an exception if window doesn't exist.
  96. // Just like when handling a window resize, this will replace the canvas and depth buffer.
  97. // Any old handles to canvas and depth buffer will become useless, so fetch new image handles from the window to avoid black flickering.
  98. void window_setPixelScale(const Window& window, int scale);
  99. // Full screen
  100. void window_setFullScreen(const Window& window, bool enabled);
  101. bool window_isFullScreen(const Window& window);
  102. // Fetch the window's surfaces
  103. // Always get the canvas (and any depth buffer) after calls to window_executeEvents or window_setPixelScale,
  104. // because these may replace the canvas with a new size.
  105. // TODO: Prevent the backend window from freeing the memory while the canvas is still being used.
  106. // Get the canvas/color-buffer.
  107. // Raises an exception if window doesn't exist.
  108. // The canvas size will be smaller when pixelScale is larger, because the canvas has to fit inside the window.
  109. AlignedImageRgbaU8 window_getCanvas(const Window& window);
  110. // Get the depth buffer allocated on demand.
  111. // Raises an exception if window doesn't exist.
  112. // If you never call this method, no depth buffer will be allocated.
  113. // If you call it at the same time as window_getCanvas, it will have the same size as the canvas.
  114. AlignedImageF32 window_getDepthBuffer(const Window& window);
  115. // The low-resolution canvas and depth buffer dimensions are relative to mouse events given to components.
  116. // Because component are drawn to the canvas and affected by upscaling.
  117. // Returns the width of the canvas.
  118. // Raises an exception if window doesn't exist.
  119. int window_getCanvasWidth(const Window& window);
  120. // Returns the height of the canvas.
  121. // Raises an exception if window doesn't exist.
  122. int window_getCanvasHeight(const Window& window);
  123. // The window's inner dimensions are relative to mouse events received directly from the window at full pixel resolution.
  124. // Returns the inner width of the window.
  125. // Raises an exception if window doesn't exist.
  126. int window_getInnerWidth(const Window& window);
  127. // Returns the inner height of the window.
  128. // Raises an exception if window doesn't exist.
  129. int window_getInnerHeight(const Window& window);
  130. // Direct window events
  131. // Listen to window mouse events
  132. // Raises an exception if window doesn't exist.
  133. // event.mouseEventType gives the type of mouse event
  134. // event.key gives the key being used
  135. void window_setMouseEvent(const Window& window, const MouseCallback& mouseEvent);
  136. // Listen to window keyboard events
  137. // Raises an exception if window doesn't exist.
  138. // event.keyboardEventType gives the type of keyboard event
  139. // event.dsrKey gives the key being used
  140. void window_setKeyboardEvent(const Window& window, const KeyboardCallback& keyboardEvent);
  141. // Listen to the window close event
  142. // Raises an exception if window doesn't exist.
  143. void window_setCloseEvent(const Window& window, const EmptyCallback& closeEvent);
  144. // Components
  145. // Returns true iff the component exists
  146. bool component_exists(const Component& component);
  147. // Returns true iff propertyName exists in component
  148. bool component_hasProperty(const Component& component, const ReadableString& propertyName);
  149. // Sets a property found using propertyName in component to the value serialized in value.
  150. // Raises an exception if component doesn't exist.
  151. // Matching of propertyName is case insensitive.
  152. // Returns ReturnCode::Good if assigned.
  153. // Unless mustAssign forces an exception.
  154. // Returns ReturnCode::KeyNotFound if propertyName wasn't found in component.
  155. // Unless mustAssign forces an exception.
  156. // Returns ReturnCode::ParsingFailure if propertyName was found but value couldn't be converted to its type.
  157. ReturnCode component_setProperty(const Component& component, const ReadableString& propertyName, const ReadableString& value, bool mustAssign = true);
  158. // A version for setting integers and booleans.
  159. // For integers:
  160. // Just set value to whatever you want assigned directly.
  161. // This is faster than using component_setProperty by not parsing the value from any string.
  162. // For booleans:
  163. // Use 1 (or another non-zero value) for true and 0 for false.
  164. // Boolean properties will convery any non-zero values into ones.
  165. ReturnCode component_setProperty_integer(const Component& component, const ReadableString& propertyName, int64_t value, bool mustAssign = true);
  166. // A version optimized for basic strings to bypass quote mangling
  167. // The new value is given as it is without unmangling.
  168. ReturnCode component_setProperty_string(const Component& component, const ReadableString& propertyName, const ReadableString& value, bool mustAssign = true);
  169. // Returns a property found using propertyName in component.
  170. // Raises an exception if component doesn't exist.
  171. // Matching of propertyName is case insensitive.
  172. // If mustExist is true
  173. // Raises an exception when propertyName isn't found.
  174. // If mustExist is false
  175. // Returns an empty string when propertyName isn't found.
  176. String component_getProperty(const Component& component, const ReadableString& propertyName, bool mustExist = true);
  177. // A version for setting integers and booleans.
  178. // Returns defaultValue on failure, which should use a value that is never actually used.
  179. int64_t component_getProperty_integer(const Component& component, const ReadableString& propertyName, bool mustExist = true, int64_t defaultValue = 0);
  180. // A version optimized for basic strings to bypass quote mangling.
  181. // Returns the result without adding any quote signs or escape characters.
  182. String component_getProperty_string(const Component& component, const ReadableString& propertyName, bool mustExist = true);
  183. // Call a named method in the component using optional text arguments
  184. String component_call(const Component& component, const ReadableString& methodName);
  185. String component_call(const Component& component, const ReadableString& methodName, const ReadableString& arguments);
  186. // Component events
  187. // The main activation of clickable components.
  188. // The pressed callback doesn't take any arguments, because it should be possible to generate from multiple input methods.
  189. void component_setPressedEvent(const Component& component, const EmptyCallback& event);
  190. // Mouse-down activates when any mouse button is pressed down within the component
  191. // Raises an exception if component doesn't exist.
  192. // The component itself decides if the mouse is inside, which allow rounded components to act as their true shape.
  193. void component_setMouseDownEvent(const Component& component, const MouseCallback& mouseEvent);
  194. // Mouse-up should eventually follow after a mouse-down event, to ensure basic transaction safety.
  195. // Raises an exception if component doesn't exist.
  196. // * Even if the mouse is dragged outside of the component or window before being lifted.
  197. // * Even if the component is removed from the window while the button is pressed,
  198. // the button press will keep it alive long enough to receive the mouse-up event before being freed.
  199. void component_setMouseUpEvent(const Component& component, const MouseCallback& mouseEvent);
  200. // Mouse-move is triggered when the mouse moves over the component.
  201. // Raises an exception if component doesn't exist.
  202. // * When pressed down inside of the component, dragging outside the component or even window will
  203. // continue to give mouse-move events to the callback.
  204. // * If dragging left of or above the window, event.position may contain negative coordinates.
  205. void component_setMouseMoveEvent(const Component& component, const MouseCallback& mouseEvent);
  206. // Mouse-scroll is triggered by scrolling in any direction.
  207. // Raises an exception if component doesn't exist.
  208. // Currently only supporting MouseKeyEnum::ScrollUp and MouseKeyEnum::ScrollDown as values in event.key.
  209. void component_setMouseScrollEvent(const Component& component, const MouseCallback& mouseEvent);
  210. // Key-down only comes when a button is pressed down. (No repeat)
  211. // Raises an exception if component doesn't exist.
  212. // The backend window is responsible to filter away any false positives for down events caused by repetition.
  213. void component_setKeyDownEvent(const Component& component, const KeyboardCallback& keyboardEvent);
  214. // Key-up only comes when a button is lifted after being pressed. (No repeat)
  215. // Raises an exception if component doesn't exist.
  216. void component_setKeyUpEvent(const Component& component, const KeyboardCallback& keyboardEvent);
  217. // Key-type comes both when a key is pressed, and then repeatedly without having to lift the key.
  218. // Raises an exception if component doesn't exist.
  219. // There's usually a second's delay before quickly repeating.
  220. void component_setKeyTypeEvent(const Component& component, const KeyboardCallback& keyboardEvent);
  221. // Select events are sent when the selected index of something has changed.
  222. // Used in Listbox to cover updates from all different ways the selection may change.
  223. void component_setSelectEvent(const Component& component, const IndexCallback& selectEvent);
  224. // Theme
  225. // Apply the given theme recursively to all components in the window's interface.
  226. // Raises an exception if window or component doesn't exist.
  227. // Components will gather what they can from the theme and save it for later.
  228. // Changing a theme while being used by an interface or adding new components,
  229. // should apply the theme again to ensure that all changes are applied.
  230. // TODO: Automate this process by storing a reference to the theme in each component and checking for updates before drawing.
  231. void window_applyTheme(const Window& window, const VisualTheme& theme);
  232. }
  233. #endif