Audio plugin host https://kx.studio/carla
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

juce_ComponentBuilder.h 11KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247
  1. /*
  2. ==============================================================================
  3. This file is part of the JUCE library.
  4. Copyright (c) 2022 - Raw Material Software Limited
  5. JUCE is an open source library subject to commercial or open-source
  6. licensing.
  7. By using JUCE, you agree to the terms of both the JUCE 7 End-User License
  8. Agreement and JUCE Privacy Policy.
  9. End User License Agreement: www.juce.com/juce-7-licence
  10. Privacy Policy: www.juce.com/juce-privacy-policy
  11. Or: You may also use this code under the terms of the GPL v3 (see
  12. www.gnu.org/licenses).
  13. JUCE IS PROVIDED "AS IS" WITHOUT ANY WARRANTY, AND ALL WARRANTIES, WHETHER
  14. EXPRESSED OR IMPLIED, INCLUDING MERCHANTABILITY AND FITNESS FOR PURPOSE, ARE
  15. DISCLAIMED.
  16. ==============================================================================
  17. */
  18. namespace juce
  19. {
  20. //==============================================================================
  21. /**
  22. Loads and maintains a tree of Components from a ValueTree that represents them.
  23. To allow the state of a tree of components to be saved as a ValueTree and re-loaded,
  24. this class lets you register a set of type-handlers for the different components that
  25. are involved, and then uses these types to re-create a set of components from its
  26. stored state.
  27. Essentially, to use this, you need to create a ComponentBuilder with your ValueTree,
  28. then use registerTypeHandler() to give it a set of type handlers that can cope with
  29. all the items in your tree. Then you can call getComponent() to build the component.
  30. Once you've got the component you can either take it and delete the ComponentBuilder
  31. object, or if you keep the ComponentBuilder around, it'll monitor any changes in the
  32. ValueTree and automatically update the component to reflect these changes.
  33. @tags{GUI}
  34. */
  35. class JUCE_API ComponentBuilder : private ValueTree::Listener
  36. {
  37. public:
  38. /** Creates a ComponentBuilder that will use the given state.
  39. Once you've created your builder, you should use registerTypeHandler() to register some
  40. type handlers for it, and then you can call createComponent() or getManagedComponent()
  41. to get the actual component.
  42. */
  43. explicit ComponentBuilder (const ValueTree& state);
  44. /** Creates a builder that doesn't have a state object. */
  45. ComponentBuilder();
  46. /** Destructor. */
  47. ~ComponentBuilder() override;
  48. /** This is the ValueTree data object that the builder is working with. */
  49. ValueTree state;
  50. //==============================================================================
  51. /** Returns the builder's component (creating it if necessary).
  52. The first time that this method is called, the builder will attempt to create a component
  53. from the ValueTree, so you must have registered some suitable type handlers before calling
  54. this. If there's a problem and the component can't be created, this method returns nullptr.
  55. The component that is returned is owned by this ComponentBuilder, so you can put it inside
  56. your own parent components, but don't delete it! The ComponentBuilder will delete it automatically
  57. when the builder is destroyed. If you want to get a component that you can delete yourself,
  58. call createComponent() instead.
  59. The ComponentBuilder will update this component if any changes are made to the ValueTree, so if
  60. there's a chance that the tree might change, be careful not to keep any pointers to sub-components,
  61. as they may be changed or removed.
  62. */
  63. Component* getManagedComponent();
  64. /** Creates and returns a new instance of the component that the ValueTree represents.
  65. The caller is responsible for using and deleting the object that is returned. Unlike
  66. getManagedComponent(), the component that is returned will not be updated by the builder.
  67. */
  68. Component* createComponent();
  69. //==============================================================================
  70. /**
  71. The class is a base class for objects that manage the loading of a type of component
  72. from a ValueTree.
  73. To store and re-load a tree of components as a ValueTree, each component type must have
  74. a TypeHandler to represent it.
  75. @see ComponentBuilder::registerTypeHandler(), Drawable::registerDrawableTypeHandlers()
  76. */
  77. class JUCE_API TypeHandler
  78. {
  79. public:
  80. //==============================================================================
  81. /** Creates a TypeHandler.
  82. The valueTreeType must be the type name of the ValueTrees that this handler can parse.
  83. */
  84. explicit TypeHandler (const Identifier& valueTreeType);
  85. /** Destructor. */
  86. virtual ~TypeHandler();
  87. /** Returns the type of the ValueTrees that this handler can parse. */
  88. const Identifier type;
  89. /** Returns the builder that this type is registered with. */
  90. ComponentBuilder* getBuilder() const noexcept;
  91. //==============================================================================
  92. /** This method must create a new component from the given state, add it to the specified
  93. parent component (which may be null), and return it.
  94. The ValueTree will have been pre-checked to make sure that its type matches the type
  95. that this handler supports.
  96. There's no need to set the new Component's ID to match that of the state - the builder
  97. will take care of that itself.
  98. */
  99. virtual Component* addNewComponentFromState (const ValueTree& state, Component* parent) = 0;
  100. /** This method must update an existing component from a new ValueTree state.
  101. A component that has been created with addNewComponentFromState() may need to be updated
  102. if the ValueTree changes, so this method is used to do that. Your implementation must do
  103. whatever's necessary to update the component from the new state provided.
  104. The ValueTree will have been pre-checked to make sure that its type matches the type
  105. that this handler supports, and the component will have been created by this type's
  106. addNewComponentFromState() method.
  107. */
  108. virtual void updateComponentFromState (Component* component, const ValueTree& state) = 0;
  109. private:
  110. //==============================================================================
  111. friend class ComponentBuilder;
  112. ComponentBuilder* builder;
  113. JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (TypeHandler)
  114. };
  115. //==============================================================================
  116. /** Adds a type handler that the builder can use when trying to load components.
  117. @see Drawable::registerDrawableTypeHandlers()
  118. */
  119. void registerTypeHandler (TypeHandler* type);
  120. /** Tries to find a registered type handler that can load a component from the given ValueTree. */
  121. TypeHandler* getHandlerForState (const ValueTree& state) const;
  122. /** Returns the number of registered type handlers.
  123. @see getHandler, registerTypeHandler
  124. */
  125. int getNumHandlers() const noexcept;
  126. /** Returns one of the registered type handlers.
  127. @see getNumHandlers, registerTypeHandler
  128. */
  129. TypeHandler* getHandler (int index) const noexcept;
  130. /** Registers handlers for various standard juce components. */
  131. void registerStandardComponentTypes();
  132. //==============================================================================
  133. /** This class is used when references to images need to be stored in ValueTrees.
  134. An instance of an ImageProvider provides a mechanism for converting an Image to/from
  135. a reference, which may be a file, URL, ID string, or whatever system is appropriate in
  136. your app.
  137. When you're loading components from a ValueTree that may need a way of loading images, you
  138. should call ComponentBuilder::setImageProvider() to supply a suitable provider before
  139. trying to load the component.
  140. @see ComponentBuilder::setImageProvider()
  141. */
  142. class JUCE_API ImageProvider
  143. {
  144. public:
  145. ImageProvider() = default;
  146. virtual ~ImageProvider() = default;
  147. /** Retrieves the image associated with this identifier, which could be any
  148. kind of string, number, filename, etc.
  149. The image that is returned will be owned by the caller, but it may come
  150. from the ImageCache.
  151. */
  152. virtual Image getImageForIdentifier (const var& imageIdentifier) = 0;
  153. /** Returns an identifier to be used to refer to a given image.
  154. This is used when a reference to an image is stored in a ValueTree.
  155. */
  156. virtual var getIdentifierForImage (const Image& image) = 0;
  157. };
  158. //==============================================================================
  159. /** Gives the builder an ImageProvider object that the type handlers can use when
  160. loading images from stored references.
  161. The object that is passed in is not owned by the builder, so the caller must delete
  162. it when it is no longer needed, but not while the builder may still be using it. To
  163. clear the image provider, just call setImageProvider (nullptr).
  164. */
  165. void setImageProvider (ImageProvider* newImageProvider) noexcept;
  166. /** Returns the current image provider that this builder is using, or nullptr if none has been set. */
  167. ImageProvider* getImageProvider() const noexcept;
  168. //==============================================================================
  169. /** Updates the children of a parent component by updating them from the children of
  170. a given ValueTree.
  171. */
  172. void updateChildComponents (Component& parent, const ValueTree& children);
  173. /** An identifier for the property of the ValueTrees that is used to store a unique ID
  174. for that component.
  175. */
  176. static const Identifier idProperty;
  177. private:
  178. //==============================================================================
  179. OwnedArray<TypeHandler> types;
  180. std::unique_ptr<Component> component;
  181. ImageProvider* imageProvider;
  182. #if JUCE_DEBUG
  183. WeakReference<Component> componentRef;
  184. #endif
  185. void valueTreePropertyChanged (ValueTree&, const Identifier&) override;
  186. void valueTreeChildAdded (ValueTree&, ValueTree&) override;
  187. void valueTreeChildRemoved (ValueTree&, ValueTree&, int) override;
  188. void valueTreeChildOrderChanged (ValueTree&, int, int) override;
  189. void valueTreeParentChanged (ValueTree&) override;
  190. JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (ComponentBuilder)
  191. };
  192. } // namespace juce