Trace:
Differences
This shows you the differences between two versions of the page.
Both sides previous revision Previous revision Next revision | Previous revision Next revision Both sides next revision | ||
jvx:reference [2018/05/08 07:56] admin |
jvx:reference [2020/06/24 15:40] cduncan [Inlined class] |
||
---|---|---|---|
Line 2: | Line 2: | ||
~~Title: JVx Concepts and Reference~~ | ~~Title: JVx Concepts and Reference~~ | ||
- | Version: 1.0 / 2018-04-17 | + | Version: 1.0 / 2019-07-01 |
====== Introduction ====== | ====== Introduction ====== | ||
- | This collection of various tutorials is aimed to provide you with a broad overview over the concepts and mechanics of the [[https://sourceforge.net/projects/jvx/|JVx]] application framework. | + | This collection of various tutorials is aimed at providing you with a broad overview over the concepts and mechanics of the [[https://sourceforge.net/projects/jvx/|JVx]] application framework. |
====== Of Technologies and Factories ====== | ====== Of Technologies and Factories ====== | ||
- | Let’s talk about the UI layer, the implementations and the factory that powers it all. | + | Let’s talk about the UI layer, the implementations, and the factory that powers it all. |
- | ===== The basics ===== | + | ===== The Basics ===== |
- | For everyone who does not know, [[https://sourceforge.net/projects/jvx/|JVx]] allows you to write code once and run it on different GUI frameworks, without changing your code. This is achieved by hiding the concrete GUI implementations behind our own classes, the UI classes, and providing “bindings” for different GUI frameworks behind the scenes. Such a “[[https://en.wikipedia.org/wiki/Single_source_publishing|single sourcing]]” approach has many advantages, and just one of them is that migrating to a new GUI framework requires only the change of a single line, the one which controls which factory is used. | + | For everyone who does not know, [[https://sourceforge.net/projects/jvx/|JVx]] allows you to write code once and run it on different GUI frameworks without changing your code. This is achieved by hiding the concrete GUI implementations behind our own classes, the UI classes, and providing “bindings” for different GUI frameworks behind the scenes. Such a “[[https://en.wikipedia.org/wiki/Single-source_publishing|single sourcing]]” approach has many advantages, one of which is that migrating to a new GUI framework requires only the change of a single line: the one that controls which factory is used. |
- | ===== The patterns ===== | + | ===== The Patterns ===== |
- | [[https://en.wikipedia.org/wiki/Factory_%28object_oriented_programming%29|The factory pattern]] is an important pattern in [[https://en.wikipedia.org/wiki/Object_oriented_programming|Object-oriented programming]], it empowers us to delegate the creation of objects to another object which must not be known at design and/or compile time. That allows us to use objects which have not been created by us but merely “provided” to us by an, for us unknown, source. | + | [[https://en.wikipedia.org/wiki/Factory_%28object-oriented_programming%29|The factory pattern]] is an important pattern in [[https://en.wikipedia.org/wiki/Object-oriented_programming|object-oriented programming]] It empowers us to delegate the creation of objects to another object that is not known at design and/or compile time. That allows us to use objects which have not been created by us but merely “provided” to us by an unknown-to-us source. |
- | [[https://en.wikipedia.org/wiki/Bridge_pattern|The bridge pattern]] on the other hand describes a technique which wraps implementations in another implementation and forwards all/most functionality to that wrapped implementation. This allows us to mix and match functionality without the need to have it in all implementations at once. | + | [[https://en.wikipedia.org/wiki/Bridge_pattern|The bridge pattern]], on the other hand, describes a technique which wraps implementations in another implementation and forwards all or most functionality to that wrapped implementation. This allows us to mix and match functionality without the need to have it in all implementations at once. |
- | ===== Like an onion ===== | + | ===== Like an Onion ===== |
- | [[https://sourceforge.net/projects/jvx/|JVx]] is separated into different layers, with the UI layer being at the top and of the most concern to users. | + | [[https://sourceforge.net/projects/jvx/|JVx]] is separated into different layers with the UI layer being at the top and of the most concern to users. |
{{:jvx:reference:layers.png?nolink|The four layers of VisionX: UI, Implementation, Extension and Technology.}} | {{:jvx:reference:layers.png?nolink|The four layers of VisionX: UI, Implementation, Extension and Technology.}} | ||
Line 30: | Line 30: | ||
==== Technology ==== | ==== Technology ==== | ||
- | Obviously, the first one in the chain is the so called “technology” layer. It represents the UI technology, for example Swing, JavaFX or Vaadin, which is used to power the [[https://sourceforge.net/projects/jvx/|JVx]] application. | + | Obviously, the first one in the chain is the so-called “technology” layer. It represents the UI technology -- for example Swing, JavaFX or Vaadin -- that is used to power the [[https://sourceforge.net/projects/jvx/|JVx]] application. |
- | To put it into a more simple term: | + | To put it more simply: |
<code java> | <code java> | ||
Line 39: | Line 39: | ||
==== Extension ==== | ==== Extension ==== | ||
- | Next comes the extension layer, components from the technology are extended to support needed features of [[https://sourceforge.net/projects/jvx/|JVx]]. This includes creating bindings for the databook, additional style options and changing of behavior if necessary. From time to time this also includes creating components from scratch if the provided ones do not meet the needs or there simply are none with the required functionality. For the most part, we do our best that these layers can be used without [[https://sourceforge.net/projects/jvx/|JVx]], meaning that they represent a solitary extension to the technology. A very good example is our JavaFX implementation, which compiles into two separate jars, the first being the complete [[https://sourceforge.net/projects/jvxfx/|JVx/JavaFX]] stack, the second being stand-alone JavaFX extensions which can be used in any application and without [[https://sourceforge.net/projects/jvx/|JVx]]. | + | Next comes the extension layer. Components from the technology are extended to support needed features of [[https://sourceforge.net/projects/jvx/|JVx]]. This includes creating bindings for the databook, additional style options, and changing of behavior, if necessary. From time to time, this also includes creating components from scratch if the provided ones do not meet the needs, or there simply are none with the required functionality. For the most part, we do our best that these layers can be used without [[https://sourceforge.net/projects/jvx/|JVx]], meaning that they represent a solitary extension to the technology. A very good example is our JavaFX implementation, which compiles into two separate jars, the first being the complete [[https://sourceforge.net/projects/jvxfx/|JVx/JavaFX]] stack, the second being stand-alone JavaFX extensions that can be used in any application and without [[https://sourceforge.net/projects/jvx/|JVx]]. |
- | Theoretically one can skip this layer and directly jump to the Implementation layer, but so far it has proven necessary (for cleanliness of the code, object structure and sanity reasons) to create a separate extension layer. | + | Theoretically, one can skip this layer and directly jump to the implementation layer, but, so far, it has proven necessary (for cleanliness of the code, object structure, and sanity reasons) to create a separate extension layer. |
<code java> | <code java> | ||
Line 48: | Line 48: | ||
==== Implementation ==== | ==== Implementation ==== | ||
- | After that comes the implementation layer. These implementations of the [[https://sourceforge.net/projects/jvx/|JVx]] interfaces are the actual objects returned by the factory. This is some sort of “glue” layer, it binds the technology or extended components against the interfaces which are provided by [[https://sourceforge.net/projects/jvx/|JVx]]. | + | After that comes the implementation layer. These implementations of the [[https://sourceforge.net/projects/jvx/|JVx]] interfaces are the actual objects returned by the factory. This is some sort of “glue” layer: it binds the technology or extended components against the interfaces which are provided by [[https://sourceforge.net/projects/jvx/|JVx]]. |
<code java> | <code java> | ||
Line 55: | Line 55: | ||
==== UI ==== | ==== UI ==== | ||
- | Last but for sure not least is the UI layer, which wraps the implementations. It is completely Implementation independent, that means that one can swap out the stack underneath: | + | Last, but definitely not least, is the UI layer, which wraps the implementations. It is completely implementation-independent, which means that one can swap out the stack underneath: |
{{:jvx:reference:swappable-layers.png?nolink|The Extension, Implementation and Technology can be swapped at will}} | {{:jvx:reference:swappable-layers.png?nolink|The Extension, Implementation and Technology can be swapped at will}} | ||
- | This is achieved because the UI layer is not extending the Implementation layer, but wrapping instances provided by the factory. It is oblivious to what Technology is actually underneath it. | + | This is achieved because the UI layer is not extending the implementation layer but wrapping instances provided by the factory. It is oblivious to what technology is actually underneath it. |
<code java> | <code java> | ||
Line 66: | Line 66: | ||
SwingButton resource = SwingFactory.createButton() | SwingButton resource = SwingFactory.createButton() | ||
</code> | </code> | ||
- | ===== Why is the UI layer necessary? ===== | + | ===== Why is the UI Layer Necessary? ===== |
- | It isn’t, not at all. The Implementations could be used directly without any problems, but having yet another layer has two key benefits: | + | It isn’t, not at all. The implementations could be used directly without any problems, but having yet another layer has two key benefits: |
* It allows easier usage. | * It allows easier usage. | ||
- | * It allows to add Technology independent features. | + | * It allows to add technology-independent features. |
- | By wrapping it one more time we gain a lot of freedom which we would not have otherwise, when it comes to features as when it comes to coding. The user does not need to call the factory directly and instead just needs to create a new object: | + | By wrapping it one more time, we gain a lot of freedom which we would not have otherwise when it comes to features and coding. The user does not need to call the factory directly and, instead, just needs to create a new object: |
<code java> | <code java> | ||
IButton button = new UIButton(); | IButton button = new UIButton(); | ||
</code> | </code> | ||
- | Internally, of course, the Factory is called and an implementation instance is created, but that is an implementation detail. If we would use the implementation layer directly, our code would either need to know about the implementations, which doesn’t follow the single-sourcing principle: | + | Internally, of course, the factory is called and an implementation instance is created, but that is an implementation detail. If we would use the implementation layer directly, our code would need to know about the implementations, which doesn’t follow the single-sourcing principle: |
<code java> | <code java> | ||
Line 88: | Line 88: | ||
IButton button = UIFactoryManager.getFactory().createButton(); | IButton button = UIFactoryManager.getFactory().createButton(); | ||
</code> | </code> | ||
- | Both can be avoided by using another layer which does the factory calls for us: | + | Both can be avoided by using another layer that the factory calls for us: |
<code java> | <code java> | ||
Line 106: | Line 106: | ||
} | } | ||
</code> | </code> | ||
- | Additionally this layer allows us to implement features which can be technology independent, our naming scheme, which we created during stress testing of an Vaadin application, is a very good example of that. The names of the components are derived in the UI layer without any knowledge of the underlying Technology or Implementation. | + | Additionally, this layer allows us to implement features that can be technology-independent. Our naming scheme, which we created during stress testing of a Vaadin application, is a very good example of that. The names of the components are derived in the UI layer without any knowledge of the underlying technology or implementation. |
- | Also it does provide us (and everyone else of course) with a layer which allows to rapidly and easily build [[#compound_components|compound components]] out of already existing ones, like this: | + | Also, it provides us (and everyone else, of course) with a layer which allows to rapidly and easily build [[#compound_components|compound components]] out of already existing ones, like this: |
<code java> | <code java> | ||
Line 134: | Line 134: | ||
} | } | ||
</code> | </code> | ||
- | Of course that is not even close to sophisticated, or a good example for that matter. But it shows that one can build new components out of already existing ones without having to deal with the Technology or Implementation at all, creating truly cross-technology controls. | + | Of course, that is not even close to sophisticated, or even a good example for that matter. However, it shows that one can build new components out of already existing ones without having to deal with the technology or implementation at all, creating truly cross-technology controls. |
===== The Factory ===== | ===== The Factory ===== | ||
- | The heart piece of the UI layer is the Factory, which is creating the implemented classes. It’s a rather simple system, a singleton which is set to the Technology specific implementation and can be retrieved later: | + | The heart piece of the UI layer is the factory that is creating the implemented classes. It’s a rather simple system, a singleton which is set to the technology-specific implementation and can be retrieved later: |
<code java> | <code java> | ||
Line 166: | Line 166: | ||
It “just returns new objects” from the implementation layer. That’s about it when it comes to the factory, it is as simple as that. | It “just returns new objects” from the implementation layer. That’s about it when it comes to the factory, it is as simple as that. | ||
- | ===== Piecing it together ===== | + | ===== Piecing It Together ===== |
With all this in mind, we know now that [[https://sourceforge.net/projects/jvx/|JVx]] has swappable implementations underneath its UI layer for each technology it utilizes: | With all this in mind, we know now that [[https://sourceforge.net/projects/jvx/|JVx]] has swappable implementations underneath its UI layer for each technology it utilizes: | ||
Line 172: | Line 172: | ||
{{:jvx:reference:multi-layers.png?nolink|Multiple Extensions/Implementations/Technologies can be used}} | {{:jvx:reference:multi-layers.png?nolink|Multiple Extensions/Implementations/Technologies can be used}} | ||
- | Changing between them can be as easy as setting a different factory. I say “can”, because that is only true for Swing, JavaFX and similar technologies, Vaadin, obviously, requires some more setup work. I mean, theoretically one could embed a complete application server and launch it when the factory for Vaadin is created, allowing the application to be basically stand-alone and be started as easily as a Swing application. That is possible. | + | Changing between them can be as easy as setting a different factory. I say “can” because that is only true for Swing, JavaFX, and similar technologies. Vaadin, obviously, requires some more setup work. Theoretically, one could embed a complete application server and launch it when the factory for Vaadin is created, allowing the application to be basically stand alone and started as easily as a Swing application. That is possible. |
- | ===== What else? ===== | + | ===== What Else? ===== |
- | That is how [[https://sourceforge.net/projects/jvx/|JVx]] works in regards to the UI layer. It depends on “technology specific stacks” which can be swapped out and implemented for pretty much every GUI framework out there. We currently provide support for Swing, JavaFX and Vaadin, but we also had implementations for GWT and Qt. Additionally we do support a “headless” implementation which uses lightweight objects which can be serialized and send over the wire without much effort. | + | That is how [[https://sourceforge.net/projects/jvx/|JVx]] works in regards to the UI layer. It depends on “technology-specific stacks”, which can be swapped out and implemented for pretty much every GUI framework out there. We currently provide support for Swing, JavaFX, and Vaadin, but we also had implementations for GWT and Qt. Additionally, we support a “headless” implementation, which uses lightweight objects that can be serialized and send over the wire without much effort. |
- | ===== Adding a new Technology ===== | + | ===== Adding a New Technology ===== |
- | Adding support for a new Technology is as straightforward as one can imagine, simply creating the Extensions/Implementations layers and implementing the factory for that Technology. Giving a complete manual would be out for scope for this document, but the most simple approach to adding a new stack to [[https://sourceforge.net/projects/jvx/|JVx]] is to start with stubbing out the ''%%IFactory%%'' and implementing ''%%IWindow%%''. Once that one window shows up, it’s just implementing one interface after another in a quite straightforward manner. And in the end, your application can switch to yet another GUI framework without the need to change your code. | + | Adding support for a new technology is as straightforward as one can imagine: simply create the extensions/implementations layers and implement the factory for that technology. Giving a complete manual would be out for scope for this document, but the most simple approach to adding a new stack to [[https://sourceforge.net/projects/jvx/|JVx]] is to start with stubbing out the ''%%IFactory%%'' and implementing ''%%IWindow%%''. Once that one window shows up, it’s just implementing one interface after another in a quite straightforward manner. In the end, your application can switch to yet another GUI framework without the need to change your code. |
===== Conclusion ===== | ===== Conclusion ===== | ||
- | Even though the stack of [[https://sourceforge.net/projects/jvx/|JVx]] is more complicated compared with other GUI or application frameworks, this complexity is set off by the benefits it brings. One can change the used GUI Technology without much effort and, most important of all, without touching the application logic at all. | + | Even though the stack of [[https://sourceforge.net/projects/jvx/|JVx]] is more complicated compared with other GUI or application frameworks, this complexity is set off by the benefits it brings. One can change the used GUI technology without much effort and, most importantly, without touching the application logic at all. |
- | ====== Resource and UIResource ====== | + | ====== Resource and UI Resource ====== |
- | Let’s talk about Resources and UIResources, and why they sound similar but are not the same. | + | Let’s talk about resources and UI resources and why they sound similar yet are not the same. |
===== The Basics ===== | ===== The Basics ===== | ||
- | We’ve [[#encapsulated_by_a_wrapper_class|encapsulated by a wrapper class]]. An “UIResource” on the other hand is an encapsulated concrete implementation of one of the interfaces on the UI layer. | + | We’ve [[#encapsulated_by_a_wrapper_class|encapsulated by a wrapper class]]. A “UI resource”, on the other hand, is an encapsulated concrete implementation of one of the interfaces on the UI layer. |
- | Let’s do a short brush-up on how the [[https://sourceforge.net/projects/jvx/|JVx]] architecture looks like in regards to the GUI stack: | + | Let’s do a short overview of how the [[https://sourceforge.net/projects/jvx/|JVx]] architecture looks like in regards to the GUI stack: |
- | {{:jvx:reference:resource.png?nolink|The JVx layers revisited. UI-Wrapper and Implementation implement the interface, Extension and Technology do not.}} | + | {{:jvx:reference:resource.png?nolink|The JVx layers revisited. UI wrapper and implementation implement the interface, extension and technology do not.}} |
- | The UI Wrappers are the main UI classes which are used to create the GUI (f.e. ''%%UIButton%%''). These are wrapping the Implementations (f.e. ''%%SwingButton%%'') which themselves are wrapping the Extension/Technology (f.e. a ''%%JVxButton%%''/''%%JButton%%''). Only the UI and Implementation classes are implementing the interface are required for the component (f.e. ''%%IButton%%''). That also means that the Implementation is dependent on the Extension/Technology component, but the UI can use any object which implements the interface. | + | The UI wrappers are the main UI classes that are used to create the GUI (e.g., ''%%UIButton%%''). These are wrapping the implementations (e.g., ''%%SwingButton%%''), which themselves are wrapping the extension/technology (e.g., a ''%%JVxButton%%''/''%%JButton%%''). Only the UI and implementation classes implementing the interface are required for the component (e.g., ''%%IButton%%''). That also means that the implementation is dependent on the extension/technology component, but the UI can use any object which implements the interface. |
- | Now, with that knowledge we can start defining what is what: | + | Now, with that knowledge, we can start defining what is what: |
- | {{:jvx:reference:resource2.png?nolink|The UI-Wrapper is the uicomponent, the Implementation is the uiresource and the Extension and Technology are the resource.}} | + | {{:jvx:reference:resource2.png?nolink|The UI wrapper is the UI component, the implementation is the UI resource, and the extension and technology are the resource.}} |
- | The resource itself, accessed by calling ''%%<uiwrapper>.getResource()%%'', is the Extension/Technology component. The uiresource can be accessed by calling ''%%<uiwrapper>.getUIResource()%%''. The uicomponent can be accessed by calling ''%%<uiwrapper>.getUIComponent()%%'' and is usually the UI Wrapper class itself. If we use our previous Swing example, the resource would be a ''%%JVxButton%%''/''%%JButton%%'', the uiresource would be the ''%%SwingButton%%'' and the uicomponent would be the ''%%UIButton%%''. | + | The resource itself, accessed by calling ''%%<uiwrapper>.getResource()%%'', is the extension/technology component. The UI resource can be accessed by calling ''%%<uiwrapper>.getUIResource()%%''. The UI component can be accessed by calling ''%%<uiwrapper>.getUIComponent()%%'' and is usually the UI wrapper class itself. If we use our previous Swing example, the resource would be a ''%%JVxButton%%''/''%%JButton%%'', the UI resource would be the ''%%SwingButton%%'' and the UI component would be the ''%%UIButton%%''. |
- | As one can see, access to all objects which are comprising the GUI is at all times possible. We, of course, have the UI component, we can access the Implementation component and we can access the Extension/Technology component. Theoretically we could also swap them at runtime, but in [[https://sourceforge.net/projects/jvx/|JVx]] this is limited to the construction of the object to greatly reduce the error potential and complexity of the framework code. | + | As one can see, access to all objects which comprise GUI possible at all times. We, of course, have the UI component, we can access the implementation component, and we can access the extension/technology component. Theoretically, we could also swap them at runtime, but in [[https://sourceforge.net/projects/jvx/|JVx]], this is limited to the construction of the object to greatly reduce the potential for error and complexity of the framework code. |
- | ===== Creating custom components ===== | + | ===== Creating Custom Components ===== |
- | We will use an example from the [[#part_about_creating_custom_components|part about creating custom components]] which we will come to later. The ''%%BeepComponent%%'' is a simple ''%%UIComponent%%'' extension which contains a label and two buttons inside itself. | + | We will use an example from the [[#part_about_creating_custom_components|part about creating custom components]], which we will come to later. The ''%%BeepComponent%%'' is a simple ''%%UIComponent%%'' extension that contains a label and two buttons inside itself. |
<code java> | <code java> | ||
Line 234: | Line 234: | ||
} | } | ||
</code> | </code> | ||
- | We are setting a new UIResource (an ''%%UIPanel%%'') in the constructor (at line #5) which is to be used by the ''%%UIComponent%%''. In this case it is not an Implementation, but another UI component, but that doesn’t matter because the UIResource only must implement the expected interface. At line #15 we start using that custom UIResource. | + | We are setting a new UI resource (a ''%%UIPanel%%'') in the constructor (at line #5), which is to be used by the ''%%UI component%%''. In this case, it is not an implementation, but another UI component. However, that doesn’t matter because the UI resource must only implement the expected interface. At line #15 we start using that custom UI resource. |
- | Because UIComponent is an abstract component designed for exactly this usage, the example might not be the most exciting one, but it clearly illustrates the mechanic. | + | Because UI component is an abstract component designed for exactly this usage, the example might not be the most exciting one, but it clearly illustrates the mechanics. |
- | ===== Bolting on functionality ===== | + | ===== Bolting on Functionality ===== |
- | Also from from the [[#part_about_creating_custom_components|part about creating custom components]] we can reuse the ''%%PostfixedLabel%%'' as example: | + | Also, from the [[#part_about_creating_custom_components|part about creating custom components]], we can reuse the ''%%PostfixedLabel%%'' as example: |
<code java> | <code java> | ||
Line 251: | Line 251: | ||
}; | }; | ||
</code> | </code> | ||
- | Now ''%%testLabel%%'' will be using the ''%%PostfixedLabel%%'' internally, but with no indication to the user of the object that this is the case. This allows to extend the functionality of a component completely transparently, especially in combination with functions which do return an ''%%UIComponent%%'' and similar. | + | Now ''%%testLabel%%'' will be using the ''%%PostfixedLabel%%'' internally but with no indication to the user of the object that this is the case. This allows us to extend the functionality of a component completely transparently, especially in combination with functions that return a ''%%UI component%%'' and similar. |
- | ===== An important note about the component hierarchy ===== | + | ===== An Important Note About the Component Hierarchy ===== |
If we create a simple component extensions, like the ''%%BeepComponent%%'' above, it is important to note that there is one other layer of indirection in regards to the hierarchy on the technology layer. If we create a simple frame with the ''%%BeepComponent%%'' in it, one might expect the following hierarchy: | If we create a simple component extensions, like the ''%%BeepComponent%%'' above, it is important to note that there is one other layer of indirection in regards to the hierarchy on the technology layer. If we create a simple frame with the ''%%BeepComponent%%'' in it, one might expect the following hierarchy: | ||
Line 268: | Line 268: | ||
\-Button | \-Button | ||
</code> | </code> | ||
- | With the BeepComponent added and its sub-components as its children. However, the actual hierarchy looks like this: | + | with the BeepComponent added and its subcomponents as its children. However, the actual hierarchy looks like this: |
<code> | <code> | ||
Line 280: | Line 280: | ||
\-Button | \-Button | ||
</code> | </code> | ||
- | That is because such extended components are not “passed” to the Technology, they do only exist on the UI layer because they do not have a Technology component which could be used. That is done by adding the ''%%UIComponent%%'' to the UI parent, but for adding the actual Technology component the set UIResource is used. | + | That is because such extended components are not “passed” to the technology; they only exist on the UI layer because they do not have a technology component which could be used. That is done by adding the ''%%UI component%%'' to the UI parent, but for adding the actual technology component, the set UI resource is used. |
- | ===== The special case of containers ===== | + | ===== The Special Case of Containers ===== |
- | Another special case are containers. For example we could create a panel which does display an overlay in certain situations and we will need to use that throughout the whole application. | + | Another special case is containers. For example, we could create a panel that displays an overlay in certain situations, and we will need to use that throughout the whole application. |
{{:jvx:reference:uiresourcecontainer.png?nolink|UIResourceContainer Example}} | {{:jvx:reference:uiresourcecontainer.png?nolink|UIResourceContainer Example}} | ||
- | That means we do not want to build it every time anew, so one option would be to use a factory method to “wrap” the content, something like this: | + | That means we do not want to build it every time anew, so one option would be to use a factory method to “wrap” the content. Something like this: |
<code java> | <code java> | ||
Line 333: | Line 333: | ||
} | } | ||
</code> | </code> | ||
- | Which is easy enough, but let’s say we’d like to add logic to that wrapper, at that point it becomes more complicated. We can’t use the same technique as for custom component from above, because in that case the “overlaying panel” would simply not be displayed. However, there is a similar mechanism for containers, setting the UIResourceContainer. | + | This is easy enough, but let’s say we’d like to add logic to that wrapper. At that point, it becomes more complicated. We can’t use the same technique as the custom component from above because, in that case, the “overlaying panel” would simply not be displayed. However, there is a similar mechanism for containers: setting the UI resource container. |
- | The UIResourceContainer is another special mechanism which works similar to setting the UIResource, but it works exactly the other way round. While setting the UIResource does “hide” components from the Technology which are there in UI layer, setting the UIResourceContainer does hide components from the UI layer while there are added in the Technology. A little bit complicated, here is our example again using this technique: | + | The UI resource container is another special mechanism that works similar to setting the UI resource, but it works the other way round. While setting the UI resource “hides” components from the technology in UI layer, setting the UI resource container hides components from the UI layer while they are added in the technology. As it is a little complicated, here is our example using this technique again: |
<code java> | <code java> | ||
Line 363: | Line 363: | ||
} | } | ||
</code> | </code> | ||
- | What we’ve done is extend an UIPanel (line #1), setting it up and adding children and then we’ve declared one of its children as the UIResourceContainer (line #22). So all methods which are specific to IContainer (adding children, setting a layout, etc.) are now forwarding to the innerPanel and manipulating the contents of the OverlayedPanel directly is not directly available. | + | What we’ve done is extended a UI panel (line #1), setting it up and adding children, and then we’ve declared one of its children as the UI resource container (line #22). So all methods that are specific to UI container (adding children, setting a layout, etc.) are now forwarding to the inner panel and manipulating the contents of the overlaid panel directly. |
And here is how it is used: | And here is how it is used: | ||
Line 387: | Line 387: | ||
parentContainer.add(panel, UIBorderLayout.CENTER); | parentContainer.add(panel, UIBorderLayout.CENTER); | ||
</code> | </code> | ||
- | Notice that we can use it is any other panel (line #5) and simply add it to the parent (line #18). For a user of the API it is transparent as to whether there are more components or not, this is also visible in the created component hierarchy: | + | Notice that we can use it as any other panel (line #5) and simply add it to the parent (line #18). For a user of the API, it is transparent as to whether there are more components or not. This is also visible in the created component hierarchy: |
<code> | <code> | ||
Line 411: | Line 411: | ||
===== Conclusion ===== | ===== Conclusion ===== | ||
- | Because of the way the [[https://sourceforge.net/projects/jvx/|JVx]] framework is designed, it is easy to access all layers of the GUI framework and also facilitate the usage of these layers to create custom components and allow easy access to the wrapped components, no matter on what layer or of what kind they are. | + | Because of the way the [[https://sourceforge.net/projects/jvx/|JVx]] framework is designed, it is easy to access all layers of the GUI framework and facilitate the usage of these layers to create custom components and allow easy access to the wrapped components, no matter on what layer or of what kind they are. |
====== Launchers and Applications ====== | ====== Launchers and Applications ====== | ||
- | Let’s talk about Launchers, and how they are used to start [[https://sourceforge.net/projects/jvx/|JVx]] applications. | + | Let’s talk about launchers, and how they are used to start [[https://sourceforge.net/projects/jvx/|JVx]] applications. |
- | ===== Starting an application ===== | + | ===== Starting an Application ===== |
From a technical point of view, there are two prerequisites which must be fulfilled before a [[https://sourceforge.net/projects/jvx/|JVx]] application can run: | From a technical point of view, there are two prerequisites which must be fulfilled before a [[https://sourceforge.net/projects/jvx/|JVx]] application can run: | ||
- | * the JVM must have started. | + | * The JVM must have started. |
- | * the technology specific system must have started. | + | * The technology specific system must have started. |
- | Then, and only then, the [[https://sourceforge.net/projects/jvx/|JVx]] application can run. Depending on the implementation that is used, that can be as easily as instancing the factory (Swing, JavaFX), but can also mean that a servlet server has to start (Vaadin). Because we do not wish to encumber our applications with technology specific code, we have to entrust all this to an encapsulated entity, meaning the implementations of ''%%ILauncher%%'' and ''%%IApplication%%''. | + | Then, and only then, the [[https://sourceforge.net/projects/jvx/|JVx]] application can run. Depending on the implementation that is used, that can be as easy as instancing the factory (Swing, JavaFX), but it can also mean that a servlet server has to start (Vaadin). Because we do not wish to encumber our applications with technology-specific code, we have to entrust all this to an encapsulated entity, meaning the implementations of ''%%ILauncher%%'' and ''%%IApplication%%''. |
- | ===== Following the chain ===== | + | ===== Following the Chain ===== |
The steps for getting an application to start are as follows: | The steps for getting an application to start are as follows: | ||
- | * The first thing that must run is obviously the JVM, without it we won’t have much luck starting anything. | + | * The first thing that must run is, obviously, the JVM. Without it, we won’t have much luck starting anything! |
- | * The launcher must be created and it must start the Technology. | + | * The launcher must be created, and it must start the technology. |
- | * The launcher than creates the application which the user is seeing. | + | * The launcher then creates the application, which the user is seeing. |
{{:jvx:reference:launcher.png?nolink|First the JVM starts, then the ILauncher (the window) and finally the IApplication (the content).}} | {{:jvx:reference:launcher.png?nolink|First the JVM starts, then the ILauncher (the window) and finally the IApplication (the content).}} | ||
- | So we need two classes, the ''%%ILauncher%%'' implementation which knows how to start the Technology and the ''%%IApplication%%'' implementation. That we already knew, so let’s try to put this into code. For simplicity reasons (and because I don’t want to write a complete factory from scratch for this example) we will reuse the Swing implementation and write a new launcher and application for it. | + | So we need two classes, the ''%%ILauncher%%'' implementation that knows how to start the technology and the ''%%IApplication%%'' implementation. That we already knew, so let’s try to put this into code. For simplicity reasons (and because I don’t want to write a complete factory from scratch for this example), we will reuse the Swing implementation and write a new launcher and application for it. |
- | ===== Entry point ===== | + | ===== Entry Point ===== |
- | The ''%%Main%%'' class that we will use as example is very straightforward: | + | The ''%%main%%'' class that we will use as example is very straightforward: |
<code java> | <code java> | ||
Line 457: | Line 457: | ||
} | } | ||
</code> | </code> | ||
- | All we have to do there is start the launcher itself. As the comment suggests, there might be work required for a “real” application startup. For this example, it is all we need to do. Of course we could also directly embed this little function into the launcher implementation itself, to save us one class. | + | All we have to do there is start the launcher itself. As the comment suggests, there might be work required for a “real” application startup. For this example, however, it is all we need to do. Of course, we could also directly embed this little function into the launcher implementation itself to save us one class. |
- | ===== The launcher ===== | + | ===== The Launcher ===== |
- | The ''%%ILauncher%%'' implementation on the other hand contains quite some logic, but nothing not manageable: | + | The ''%%ILauncher%%'' implementation, on the other hand, contains quite a bit of logic but nothing unmanageable: |
<code java> | <code java> | ||
Line 540: | Line 540: | ||
} | } | ||
</code> | </code> | ||
- | In short, the launcher is kicking off the Swing thread by invoking the startup method on the main Swing thread. This startup method will instantiate the factory and then create the application. From there we only need to set it visible and then our application has started. | + | In short, the launcher is kicking off the Swing thread by invoking the startup method on the main Swing thread. This startup method will instantiate the factory and then create the application. From there, we only need to set it to visible and then our application has started. |
- | The launcher extends from ''%%SwingFrame%%'', that is required because there hasn’t been a factory created yet which could be used by UI components to create themselves. If we’d try to use an UI component before creating/setting a factory, we would obviously see the constructor of the component fail with a ''%%NullPointerException%%''. | + | The launcher extends from ''%%SwingFrame%%''. That is required because there hasn’t been a factory created yet that could be used by UI components to create themselves. If we’d try to use an UI component before creating/setting a factory, we would see the constructor of the component fail with a ''%%NullPointerException%%''. |
- | The method ''%%startup()%%'' is invoked on the main Swing thread, which also happens to be the main UI thread for [[https://sourceforge.net/projects/jvx/|JVx]] in this application. Once we are on the main UI thread we can create the application, add it and then set everything to visible. | + | The method ''%%startup()%%'' is invoked on the main Swing thread, which also happens to be the main UI thread for [[https://sourceforge.net/projects/jvx/|JVx]] in this application. Once we are on the main UI thread, we can create the application, add it, and then set everything to visible. |
- | ===== The application ===== | + | ===== The Application ===== |
- | The ''%%IApplication%%'' implementation is quite short, because we extend ''%%com.sibvisions.rad.application.Application%%'', an ''%%IApplication%%'' implementation created with UI components. | + | The ''%%IApplication%%'' implementation is quite short because we extend ''%%com.sibvisions.rad.application.Application%%'', an ''%%IApplication%%'' implementation created with UI components. |
<code java> | <code java> | ||
Line 572: | Line 572: | ||
} | } | ||
</code> | </code> | ||
- | Because the launcher has previously started the technology and created the factory we can from here on now use UI components, which means we are already independent of the underlying technology. So the ''%%IApplication%%'' implementation can already be used with different technologies and is completely independent. | + | Because the launcher has previously started the technology and created the factory, we can now use UI components, which means we are already independent of the underlying technology. So, the ''%%IApplication%%'' implementation can already be used with different technologies and is completely independent. |
- | ===== Notes on the launcher ===== | + | ===== Notes on the Launcher ===== |
- | As you might have noticed, in our example the launcher is a (window) frame, that makes sense for nearly every desktop GUI toolkit as they all depend upon a window as main method to display their applications. But the launcher could also be simpler, for example just a call to start the GUI thread. Or it could be something completely different, for example an incoming HTTP request. | + | As you might have noticed, in our example the launcher is a (window) frame. That makes sense for nearly every desktop GUI toolkit, as they all depend upon a window as the main method to display their applications. But the launcher could also be simpler: for example, just a call to start the GUI thread. Or it could be something completely different: for example, an incoming HTTP request. |
- | Also don’t forget that the launcher is providing additional functionality to the application, like saving file handles, reading and writing the configuration and similar platform and toolkit dependent operations, see the [[https://sourceforge.net/p/jvx/code/HEAD/tree/trunk/java/swing/src/com/sibvisions/rad/ui/swing/impl/SwingApplication.java|launcher for Swing for further details]]. | + | Also, don’t forget that the launcher is providing additional functionality to the application, like saving file handles, reading and writing the configuration, and similar platform and toolkit-dependent operations. See the [[https://sourceforge.net/p/jvx/code/HEAD/tree/trunk/java/swing/src/com/sibvisions/rad/ui/swing/impl/SwingApplication.java|launcher for Swing for further details]]. |
===== Conclusion ===== | ===== Conclusion ===== | ||
Line 584: | Line 584: | ||
This example demonstrates how a simple launcher is implemented and why it is necessary to have a launcher in the first place. Compared with the “[[#jvx|JVx]] are of course a lot more complex than these examples, that is because they implement all the required functionality and also take care of a lot of boiler plate operations. It is taking care of all technology specific code and allows to keep your application free from knowing about the platform it runs on. | This example demonstrates how a simple launcher is implemented and why it is necessary to have a launcher in the first place. Compared with the “[[#jvx|JVx]] are of course a lot more complex than these examples, that is because they implement all the required functionality and also take care of a lot of boiler plate operations. It is taking care of all technology specific code and allows to keep your application free from knowing about the platform it runs on. | ||
- | ====== DataBooks ====== | + | ====== Databooks ====== |
- | Let’s talk about DataBooks, which allow access to data without any effort. | + | Let’s talk about databooks, which allow access to data without any effort. |
- | ===== What is it? ===== | + | ===== What Is It? ===== |
- | DataBooks are an active model, which allow you to directly query and manipulate the data. Contrary to many other systems [[https://sourceforge.net/projects/jvx/|JVx]] does not map the data into objects, but instead allows you to directly access it in a table like fashion, exposing columns, rows and values. | + | Databooks are an active model that allow you to directly query and manipulate the data. Contrary to many other systems, [[https://sourceforge.net/projects/jvx/|JVx]] does not map the data into objects, but allows you to directly access it in a table-like fashion exposing columns, rows, and values. |
- | One could say that it is like a three dimensional array, with these dimensions: | + | One could say that it is like a three dimensional array with these dimensions: |
* DataPages | * DataPages | ||
Line 598: | Line 598: | ||
* Columns/Values | * Columns/Values | ||
- | With DataPages containing DataRows, which itself contain the values and everything is referencing the RowDefinition, which outlines how a row looks like. | + | with DataPages containing DataRows, which in turn contain the values and everything referencing the RowDefinition, which further outlines how a row looks like. |
{{:jvx:reference:databook.png?nolink|DataBook Architecture, the DataBook contains DataPages, which contain DataRows.}} | {{:jvx:reference:databook.png?nolink|DataBook Architecture, the DataBook contains DataPages, which contain DataRows.}} | ||
- | ===== RowDefinition ===== | + | ===== Row Definition ===== |
- | The RowDefinition defines what columns are available in the row and stores some additional information about them, like the names of the [[https://en.wikipedia.org/wiki/Unique_key|primary key]] columns. You can think of the RowDefinition as the headers of a table. | + | The row definition defines what columns are available in the row and stores some additional information about them, like the names of the [[https://en.wikipedia.org/wiki/Unique_key|primary key]] columns. You can think of the row definition as the headers of a table. |
- | Its creation and usage is rather simple, and if you’re working with RemoteDataBooks there is no need to create one at all, as it is automatically created when the DataBook is opened. A RowDefinition holds and manages ColumnDefinitions, which define the columns. | + | Its creation and usage is rather simple, and, if you’re working with RemoteDataBooks there is no need to create one at all, as it is automatically created when the databook is opened. A row definition holds and manages column definitions, which define the columns. |
<code java> | <code java> | ||
Line 616: | Line 616: | ||
dataBook.setRowDefinition(rowDefinition); | dataBook.setRowDefinition(rowDefinition); | ||
</code> | </code> | ||
- | ==== ColumnDefinition ==== | + | ==== Column Definition ==== |
- | The ColumnDefinition defines and provides all necessary information about the column, like its DataType, its size and if it is nullable or not. You can think of it as one column in a table. | + | The column definition defines and provides all necessary information about the column, like its datatype, its size, and whether it is nullable or not. You can think of it as one column in a table. |
<code java> | <code java> | ||
Line 624: | Line 624: | ||
columnDefinition.setNullable(false); | columnDefinition.setNullable(false); | ||
</code> | </code> | ||
- | ==== MetaData ==== | + | ==== Metadata ==== |
- | Most of the ColumnDefinition is additional information about the column, like if it is nullable, the label of the column, default values, allowed values and similar information. | + | Most of the column definition is additional information about the column, like if it is nullable, the label of the column, default values, allowed values, and similar information. |
- | ==== DataType ==== | + | ==== Data Type ==== |
- | Of course we must define what type the value in the column has, this is done by setting a DataType on the ColumnDefinition. The DataType defines what kind of values the column holds, like if it is a String, or a Number or something else. We do provide the most often used DataTypes out of the box: | + | Of course, we must define what type the value in the column has. This is done by setting a data type on the column definition. The data type defines what kind of values the column holds, like if it is a string, a number, or something else. We provide the most often used data types out of the box: |
* BigDecimal | * BigDecimal | ||
Line 640: | Line 640: | ||
* Timestamp | * Timestamp | ||
- | It is possible to add new DataTypes by simply implementing ''%%IDataType%%''. | + | It is possible to add new data types by simply implementing ''%%IDataType%%''. |
- | ===== DataRow ===== | + | ===== Data Row ===== |
- | The DataRow repesents a single row of data, it holds/references its own RowDefinition and of course provides access to the values of the row. Accessing the DataRow can be done either by column index or column name, and the methods do either return or accept Objects. Let’s look at a simple usage example: | + | The data row represents a single row of data; it holds/references its own row definition and, of course, provides access to the values of the row. Accessing the data row can be done either by column index or column name, and the methods either return or accept objects. Let’s look at a simple usage example: |
<code java> | <code java> | ||
Line 653: | Line 653: | ||
dataRow.setValue("COLUMN_A", "New Value"); | dataRow.setValue("COLUMN_A", "New Value"); | ||
</code> | </code> | ||
- | ===== DataPage ===== | + | ===== Data Page ===== |
- | The DataPage is basically a list of DataRows, it also holds its own RowDefinition which is shared with all the contained DataRows. | + | The data page is basically a list of data rows. It also holds its own row definition, which is shared with all the contained data rows. |
- | The main usage of DataPages is to allow paging in a master/detail relationship. If the master selects a different row, the detail databook does select the related DataPage. | + | The main usage of data pages is to allow paging in a master/detail relationship. If the master selects a different row, the detail databook selects the related data page. |
- | ===== DataBook ===== | + | ===== Databook ===== |
- | The DataBook is the main model of [[https://sourceforge.net/projects/jvx/|JVx]], it provides direct access to its current DataPage and DataRow by extending from IDataRow and IDataPage. | + | The databook is the main model of [[https://sourceforge.net/projects/jvx/|JVx]], it provides direct access to its current data page and data row by extending from IDataRow and IDataPage. |
- | By default, the DataBook holds one DataPage and only has multiple DataPages if it is the detail in a master/detail relationship. | + | By default, the databook holds one data page and only has multiple data pages if it is the detail in a master/detail relationship. |
- | ===== Usage example ===== | + | ===== Usage Example ===== |
- | Here is a simple usage example of a ''%%MemDataBook%%'', an ''%%IDataBook%%'' implementation which does only operate in memory: | + | Here is a simple example of a ''%%MemDataBook%%'', an ''%%IDataBook%%'' implementation that only operates in memory: |
<code java> | <code java> | ||
Line 704: | Line 704: | ||
dataBook.delete(); | dataBook.delete(); | ||
</code> | </code> | ||
- | ==== Accessing the data with Strings ==== | + | ==== Accessing the Data With Strings ==== |
- | One of the major advantages of the DataBook concept is that there is no need to create new classes to represent each table, view or query result. One can always use the DataBook, directly and easily and model changes don’t necessitate changes on the client side. The downside to this approach is that we lose compile time checks because we access the data dynamically. However, This can be mitigated by using [[https://marketplace.eclipse.org/content/eplug-jvx|EPlug, an Eclipse plugin]] which provides compile time checks and many more features. | + | One of the major advantages of the databook concept is that there is no need to create new classes to represent each table, view, or query result. One can always use the databook directly and easily, and model changes don’t necessitate changes on the client side. The downside to this approach is that we lose compile time checks because we access the data dynamically. However, this can be mitigated by using [[https://marketplace.eclipse.org/content/eplug-jvx|EPlug, an Eclipse plugin]] which provides compile time checks and many more features. |
- | ==== No primitives, Objects only ==== | + | ==== No Primitives, Objects Only ==== |
- | We do not provide overloads to fetch primitives, that is because there are mainly three types of data inside a database: | + | We do not provide overloads to fetch primitives. This is because there are mainly three types of data inside a database: |
* Numbers | * Numbers | ||
Line 716: | Line 716: | ||
* Binary Data | * Binary Data | ||
- | Text and Binary Data are both objects (arrays of primitives are Objects after all) and Numbers are either primitives or Objects. Most of the time if we deal with numbers inside a database we want them to be of arbitrary precision, which means we must represent them as ''%%BigDecimal%%''. Supporting ''%%double%%'' or ''%%float%%'' in these cases would be dangerously, because one might write a ''%%float%%'' into the database [[https://en.wikipedia.org/wiki/Floating_point_arithmetic|which might or might not end up with the correct value]] in the database. To completely eliminate such problems, we do only support Objects, which means that one is “limited” to the usage of Number extensions like ''%%BigLong%%'' and ''%%BigDecimal%%'', which do not suffer from such problems. | + | Text and binary data are both objects (arrays of primitives are objects after all) and numbers are either primitives or objects. Most of the time, if we deal with numbers inside a database, we want them to be of arbitrary precision, which means we must represent them as ''%%BigDecimal%%''. Supporting ''%%double%%'' or ''%%float%%'' in these cases would be dangerous because one might write a ''%%float%%'' into the database [[https://en.wikipedia.org/wiki/Floating-point_arithmetic|, which might or might not end up with the correct value]] in the database. To completely eliminate such problems, we only support objects, which means that one is “limited” to the usage of number extensions like ''%%BigLong%%'' and ''%%BigDecimal%%'', which do not suffer from such problems. |
- | ==== Where are the DataPages? ==== | + | ==== Where Are the Data Pages? ==== |
- | What is not clear from this example is how and when DataPages are used. As a matter of fact, most of the time there is no need to think about DataPages because they are managed directly by the DataBook, and if used like this there is only one DataPage. Multiple DataPages will be used if there is a Master/Detail relationship defined in which case the DataBook does select the correct DataPage automatically. | + | What is not clear from this example is how and when data pages are used. As a matter of fact, most of the time there is no need to think about data pages because they are managed directly by the databook, and, if used like this, there is only one data page. Multiple data pages will be used if there is a master/detail relationship defined, in which case the databook selects the correct data page automatically. |
===== Master/Detail ===== | ===== Master/Detail ===== | ||
- | [[https://en.wikipedia.org/wiki/Master%E2%80%93detail_interface#Data_model|Master/detail]] is something that occurs in nearly every data model. It means simply that there is one master dataset which is referenced by one or multiple detail datasets. Or to express it in SQL: | + | [[https://en.wikipedia.org/wiki/Master%E2%80%93detail_interface#Data_model|Master/detail]] is something that occurs in nearly every data model. It simply means that there is one master data set that is referenced by one or multiple detail data sets. Or to express it in SQL: |
<code sql> | <code sql> | ||
Line 733: | Line 733: | ||
left join DETAIL d on m.ID=d.MASTER_ID; | left join DETAIL d on m.ID=d.MASTER_ID; | ||
</code> | </code> | ||
- | We can of course express a master/detail relationship when using DataBooks. For that we just create a ''%%ReferenceDefinition%%'' and assign it to the detail DataBook: | + | We can, of course, express a master/detail relationship when using databooks. For that, we just create a ''%%ReferenceDefinition%%'' and assign it to the detail databook: |
<code java> | <code java> | ||
Line 751: | Line 751: | ||
detailDataBook.open(); | detailDataBook.open(); | ||
</code> | </code> | ||
- | Let’s assume the following data for illustration purposes: | + | Let’s assume the following data for illustrative purposes: |
<code> | <code> | ||
Line 767: | Line 767: | ||
8| 3 | 8| 3 | ||
</code> | </code> | ||
- | Now if we select the second row in the ''%%masterDataBook%%'', the ''%%detailDataBook%%'' will just contain the rows with the corresponding ''%%MASTER_ID%%'', so 3, 4 and 5. | + | Now, if we select the second row in the ''%%masterDataBook%%'', the ''%%detailDataBook%%'' will just contain the rows with the corresponding ''%%MASTER_ID%%'', so 3, 4, and 5. |
<code> | <code> | ||
Line 778: | Line 778: | ||
3 5| 2 | 3 5| 2 | ||
</code> | </code> | ||
- | The ''%%detailDataBook%%'' is automatically adjusted according to the selection in the ''%%masterDatabook%%''. Of course this can have an arbitrary depth, too. | + | The ''%%detailDataBook%%'' is automatically adjusted according to the selection in the ''%%masterDatabook%%''. Of course, this can have an arbitrary depth too. |
===== Conclusion ===== | ===== Conclusion ===== | ||
- | The DataBook is the backbone of [[https://sourceforge.net/projects/jvx/|JVx]], it provides a clean and easy way to access and manipulate data. At the same time, it is flexible and can be customized to specific needs with ease. | + | The databook is the backbone of [[https://sourceforge.net/projects/jvx/|JVx]]: it provides a clean and easy way to access and manipulate data. At the same time, it is flexible and can be customized to specific needs with ease. |
====== Application Basics ====== | ====== Application Basics ====== | ||
- | Let’s talk about the basics, how a [[https://sourceforge.net/projects/jvx/|JVx]] application starts, works and how the connection strings together the client and server side. | + | Let’s talk about the basics: how a [[https://sourceforge.net/projects/jvx/|JVx]] application starts, how it works, and how the connection strings together the client and server side. |
===== Multitier Architecture ===== | ===== Multitier Architecture ===== | ||
Line 796: | Line 796: | ||
The following method is a simplified way to launch a [[https://sourceforge.net/projects/jvx/|JVx]] application. Normally, you’d use the technology specific launcher to launch the application. These launchers do know exactly what is required to set it up and start the technology and the application. However, covering the launchers is out of scope for this post, so we will review them and their mechanics in a follow-up. | The following method is a simplified way to launch a [[https://sourceforge.net/projects/jvx/|JVx]] application. Normally, you’d use the technology specific launcher to launch the application. These launchers do know exactly what is required to set it up and start the technology and the application. However, covering the launchers is out of scope for this post, so we will review them and their mechanics in a follow-up. | ||
- | ===== The simplest JVx application: Just the GUI ===== | + | ===== The Simplest JVx Application: Just the GUI ===== |
- | But first, we will start without anything. The most simple application you can create with [[https://sourceforge.net/projects/jvx/|JVx]] is an application which does open a single window and only works with in memory data (if at all). This can be easily achieved by “just starting” the application. | + | But first, we will start without anything. The most simple application you can create with [[https://sourceforge.net/projects/jvx/|JVx]] is an application which opens a single window and only works with in-memory data (if at all). This can be easily achieved by “just starting” the application. |
- | [[https://blog.sibvisions.com/2016/12/07/jvx_reference_of_technologies_and_factories/|The JVx GUI is a simple layer on top of the Technology]] which implements the actual functionality. So if we want to have a GUI we’ll need to initialize the factory before doing anything else: | + | [[https://blog.sibvisions.com/2016/12/07/jvx-reference-of-technologies-and-factories/|The JVx GUI is a simple layer on top of the Technology]] which implements the actual functionality. So if we want to have a GUI we’ll need to initialize the factory before doing anything else: |
<code java> | <code java> | ||
UIFactoryManager.getFactoryInstance(SwingFactory.class); | UIFactoryManager.getFactoryInstance(SwingFactory.class); | ||
</code> | </code> | ||
- | With this little code we have initialized everything we need to create a simple Swing application. Now we can start to create and populate a window with something: | + | With this little code, we have initialized everything we need to create a simple Swing application. Now we can start to create and populate a window with something: |
<code java> | <code java> | ||
Line 817: | Line 817: | ||
frame.eventWindowClosed().addListener(() -> System.exit(0)); | frame.eventWindowClosed().addListener(() -> System.exit(0)); | ||
</code> | </code> | ||
- | We can start to create and manipulate the GUI, in this case we are building a simple window with a label inside. Last but not least, we make sure that the JVM will exit when the window is closed. | + | We can start to create and manipulate the GUI. In this case, we are building a simple window with a label inside. Lastly, we make sure that the JVM will exit when the window is closed. |
A very good example and showcase for that is the [[https://github.com/sibvisions/jvx.kitchensink|JVx Kitchensink]]. | A very good example and showcase for that is the [[https://github.com/sibvisions/jvx.kitchensink|JVx Kitchensink]]. | ||
- | That’s it. That is the most simple way to start a [[https://sourceforge.net/projects/jvx/|JVx]] application. We can use all controls and we can use ''%%MemDataBook%%''s without any problem or limitation. And best of all, we can simply switch to another Technology by using another factory. | + | That’s it! That is the most simple way to start a [[https://sourceforge.net/projects/jvx/|JVx]] application. We can use all controls, and we can use ''%%MemDataBook%%''s without any problem or limitation. Best of all, we can simply switch to another technology by using another factory. |
- | ===== Anatomy of a remote JVx application ===== | + | ===== Anatomy of a Remote JVx Application ===== |
- | Of course [[https://sourceforge.net/projects/jvx/|JVx]] wouldn’t be that useful if it would just provide static GUI components. Now, to explain what else is required for a remote [[https://sourceforge.net/projects/jvx/|JVx]] application I have to go far afield, so let’s head down the rabbit hole. | + | Of course, [[https://sourceforge.net/projects/jvx/|JVx]] wouldn’t be that useful if it would just provide static GUI components. Now, to explain what else is required for a remote [[https://sourceforge.net/projects/jvx/|JVx]] application, I have to go far afield, so let’s head down the rabbit hole. |
{{:jvx:reference:jvx-client-server.png?nolink| Layers}} | {{:jvx:reference:jvx-client-server.png?nolink| Layers}} | ||
Line 831: | Line 831: | ||
What you are seeing here is a rough sketch of how the architecture of [[https://sourceforge.net/projects/jvx/|JVx]] looks like. Let’s walk through the image step by step. We will look at each successive layer and work our way from the database on the server to the databook on the client. | What you are seeing here is a rough sketch of how the architecture of [[https://sourceforge.net/projects/jvx/|JVx]] looks like. Let’s walk through the image step by step. We will look at each successive layer and work our way from the database on the server to the databook on the client. | ||
- | ==== DBAccess, accessing a database ==== | + | ==== DBAccess, Accessing a Database ==== |
Accessing a database is easy when using ''%%DBAccess%%''. All we must do is to set the [[https://en.wikipedia.org/wiki/Java_Database_Connectivity|JDBC]] URL of the server and connect to it: | Accessing a database is easy when using ''%%DBAccess%%''. All we must do is to set the [[https://en.wikipedia.org/wiki/Java_Database_Connectivity|JDBC]] URL of the server and connect to it: | ||
Line 842: | Line 842: | ||
dbAccess.open(); | dbAccess.open(); | ||
</code> | </code> | ||
- | As a note, the instance returned by ''%%getDBAccess(...)%%'' is the database specific ''%%DBAccess%%'' extension, which does know how to handle its database. | + | As a note, the instance returned by ''%%getDBAccess(...)%%'' is the database-specific ''%%DBAccess%%'' extension, which knows how to handle its database. |
- | We can of course use ''%%DBAccess%%'' to directly access the database: | + | We can, of course, use ''%%DBAccess%%'' to directly access the database: |
<code java> | <code java> | ||
Line 853: | Line 853: | ||
List<Bean> data = dbAccess.executeQuery("select * from SOME_TABLE"); | List<Bean> data = dbAccess.executeQuery("select * from SOME_TABLE"); | ||
</code> | </code> | ||
- | …or manipulate the database, or query information about the database or execute procedures or do anything else. | + | …or manipulate the database, query information about the database, execute procedures, or anything else! |
- | ==== DBStorage, preparing the database access for databooks ==== | + | ==== DBStorage, Preparing the Database Access for Databooks ==== |
- | The downside of using DBAccess is that everything must be database specific. To become database agnostic we must use ''%%DBStorage%%''. ''%%DBStorage%%'' does not care which database it is connected to and can operate on any of them: | + | The downside of using DBAccess is that everything must be database-specific. To become database-neutral, we must use ''%%DBStorage%%''. ''%%DBStorage%%'' does not care which database it is connected to and can operate on any of them: |
<code java> | <code java> | ||
Line 865: | Line 865: | ||
storage.open(); | storage.open(); | ||
</code> | </code> | ||
- | We can use this to insert, update, delete and fetch data. Additionally the ''%%DBStorage%%'' does retrieve and manage the metadata of the table we’ve set, which means that we can query all column names, what type they are, we can even access the indexes and the default values. Short, the ''%%DBStorage%%'' leaves little to be desired when it comes to operating on a database. | + | We can use this to insert, update, delete and fetch data. Additionally, the ''%%DBStorage%%'' does retrieve and manage the metadata of the table we’ve set, which means that we can query all column names, what type they are, we can even access the indexes and the default values. Short, the ''%%DBStorage%%'' leaves little to be desired when it comes to operating on a database. |
- | If we query data from the ''%%DBStorage%%'' we receive a List of rows. The rows are are either represented as ''%%Object%%'' array, ''%%IBean%%'' or a POJO and we can easily manipulate the data, like this: | + | If we query data from the ''%%DBStorage%%'', we receive a list of rows. The rows are either represented as ''%%Object%%'' array, ''%%IBean%%'', or a POJO, and we can easily manipulate the data, like this: |
<code java> | <code java> | ||
Line 876: | Line 876: | ||
} | } | ||
</code> | </code> | ||
- | As one can see, it looks quite familiar to the DataBook, which isn’t a coincidence. The ''%%DBStorage%%'' “powers” the DataBooks on the server side, a DataBook will get its data from and will send its modified data to the ''%%DBStorage%%''. | + | As one can see, it looks quite familiar to the DataBook, which isn’t a coincidence. The ''%%DBStorage%%'' “powers” the databooks on the server side, a databook will get its data from and will send its modified data to the ''%%DBStorage%%''. |
- | I’ve been using the ''%%DBStorage%%'' here as an example, but actually the Storage is not dependent on a database. ''%%IStorage%%'' can be implemented to provide any sort of data provider, like reading from an XML or JSON file, scraping data from a website, fetching data from a different process or reading it directly from a hardware sensor. | + | I’ve been using the ''%%DBStorage%%'' here as an example, but actually the storage is not dependent on a database. ''%%IStorage%%'' can be implemented to provide any sort of data provider, like reading from an XML or JSON file, scraping data from a website, fetching data from a different process, or reading it directly from a hardware sensor. |
- | ==== Life Cycle Objects, the business objects with all the logic ==== | + | ==== Life Cycle Objects, the Business Objects With All the Logic ==== |
- | Life Cycle Objects, or LCOs, are the server side business objects which contain and provide the business logic. [[https://forum.sibvisions.com/viewtopic.php?t=124|They are created and destroyed as is requested by the client-side]] and are used to provide specific functionality to the client, like providing functionality specific to one screen or workflow. This is done by [[https://en.wikipedia.org/wiki/Remote_procedure_call|RPC, Remote Procedure Calls]], which means that the client is directly calling the methods defined in the LCOs, which includes getting the Storages for the DataBooks. | + | Life Cycle Objects, or LCOs, are the server side business objects which contain and provide the business logic. [[https://forum.sibvisions.com/viewtopic.php?t=124|They are created and destroyed as is requested by the client side]] and are used to provide specific functionality to the client, like providing functionality specific to one screen or workflow. This is done by [[https://en.wikipedia.org/wiki/Remote_procedure_call|RPC, Remote Procedure Calls]], which means that the client is directly calling the methods defined in the LCOs, which includes getting the Storages for the DataBooks. |
There is also a security aspect to these, as you can permit one client access to a certain LCO but lock out everyone else, which means that only that client can use the functionality provided by the LCO. | There is also a security aspect to these, as you can permit one client access to a certain LCO but lock out everyone else, which means that only that client can use the functionality provided by the LCO. | ||
Line 910: | Line 910: | ||
} | } | ||
</code> | </code> | ||
- | === Sub-Session aka Screen === | + | === Sub-Session, AKA Screen === |
The sub-session, also known as screen, LCO is the last in the chain. It provides functionality specific to a certain part of the application, like a single screen, and provides the storages required to power the databooks and other functionality. | The sub-session, also known as screen, LCO is the last in the chain. It provides functionality specific to a certain part of the application, like a single screen, and provides the storages required to power the databooks and other functionality. | ||
Line 923: | Line 923: | ||
} | } | ||
</code> | </code> | ||
- | ==== Server, serving it up ==== | + | ==== Server, Serving It Up ==== |
- | There really isn’t much to say about the server, it accepts connections and hands out sessions. Of course it is not that easy, but for this guide we will not and don’t need to go into any further detail. | + | There really isn’t much to say about the server; it accepts connections and hands out sessions. Of course, it is not that easy, but for this guide we do not need to go into any further detail. |
- | ==== Connection, connecting to a server ==== | + | ==== Connection, Connecting to a Server ==== |
- | The connection which strings together the client and the server is used for the communication between them, obviously. It can be anything, from a simple direct connection which strings two objects together to a HTTP connection which talks with a server on the other side of the planet. | + | The connection that strings together the client and the server is used for, obviously, the communication between them. It can be anything from a simple direct connection that strings two objects together to an HTTP connection that talks with a server on the other side of the planet. |
- | By default we provide different ''%%IConnection%%'' implementations, the ''%%DirectServerConnection%%'', ''%%DirectObjectConnection%%'', the ''%%HttpConnection%%'' and the ''%%VMConnection%%''. The ''%%DirectServerConnection%%'' is a simple ''%%IConnection%%'' implementation which does simply forward method calls to known objects, without a layer of indirection in between, and is used when the client and server reside inside the same JVM. The ''%%HttpConnection%%'' communicates with the server over a HTTP connection and is used whenever the client and server are not inside the same JVM. The ''%%DirectObjectConnection%%'' and ''%%VMConnection%%'' are used for unit tests. | + | By default, we provide different ''%%IConnection%%'' implementations, the ''%%DirectServerConnection%%'', ''%%DirectObjectConnection%%'', the ''%%HttpConnection%%'' and the ''%%VMConnection%%''. The ''%%DirectServerConnection%%'' is a simple ''%%IConnection%%'' implementation that forwards method calls to known objects without a layer of indirection and is used when the client and server reside inside the same JVM. The ''%%HttpConnection%%'' communicates with the server over an HTTP connection and is used whenever the client and server are not inside the same JVM. The ''%%DirectObjectConnection%%'' and ''%%VMConnection%%'' are used for unit tests. |
- | As example we will use the ''%%DirectServerConnection%%'', which serves as Server and Connection. It is used if the server and client reside in the same JVM. | + | As an example, we will use the ''%%DirectServerConnection%%'', which serves as server and connection. It is used if the server and client reside in the same JVM. |
<code java> | <code java> | ||
Line 939: | Line 939: | ||
// The connection will be automatically opened by the MasterConnection. | // The connection will be automatically opened by the MasterConnection. | ||
</code> | </code> | ||
- | ==== Master- and SubConnections, client-side lifecycle management ==== | + | ==== Master- and Sub-Connections, Client-Side Life Cycle Management ==== |
- | The ''%%MasterConnection%%'' is the main connection which is used to access the server and its functionality. When a ''%%MasterConnection%%'' is established, a Session LCO on the server is created. | + | The ''%%MasterConnection%%'' is the main connection that is used to access the server and its functionality. When a ''%%MasterConnection%%'' is established, a session LCO on the server is created. |
<code java> | <code java> | ||
Line 947: | Line 947: | ||
masterConnection.open(); | masterConnection.open(); | ||
</code> | </code> | ||
- | A ''%%SubConnection%%'' is a sub connection of the ''%%MasterConnection%%'' and allows to access specific functionality encapsulated in an LCO. When a ''%%SubConnection%%'' is established, the requested/specified LCO on the server is created and can be accessed through the ''%%SubConnection%%'' | + | A ''%%SubConnection%%'' is a sub-connection of the ''%%MasterConnection%%'' and allows us to access specific functionality encapsulated in an LCO. When a ''%%SubConnection%%'' is established, the requested/specified LCO on the server is created and can be accessed through the ''%%SubConnection%%'' |
<code java> | <code java> | ||
Line 953: | Line 953: | ||
subConnection.open(); | subConnection.open(); | ||
</code> | </code> | ||
- | The ''%%SubConnection%%'' can now access the functionality provided by the Application, the Session and the LCO which was specified. | + | The ''%%SubConnection%%'' can now access the functionality provided by the application, the session, and the LCO that was specified. |
<code java> | <code java> | ||
subConnection.callAction("doSomethingOnTheServer"); | subConnection.callAction("doSomethingOnTheServer"); | ||
</code> | </code> | ||
- | ==== DataSource, preparing the connection for the databook ==== | + | ==== DataSource, Preparing the Connection for the Databook ==== |
- | To provide data to the DataBooks we can use the connection which we’ve described earlier. However, the DataBook does not directly know about the connection, it expects an ''%%IDataSource%%'', which is used as an intermediate: | + | To provide data to the databooks, we can use the connection we’ve described earlier. However, the databook does not directly know about the connection; it expects an ''%%IDataSource%%'', which is used as an intermediate: |
<code java> | <code java> | ||
Line 966: | Line 966: | ||
dataSource.open(); | dataSource.open(); | ||
</code> | </code> | ||
- | Of course the ''%%RemoteDataSource%%'' is just one possible implementation of ''%%IDataSource%%'' which can be used to provide data to the DataBook. | + | Of course, the ''%%RemoteDataSource%%'' is just one possible implementation of ''%%IDataSource%%'' that can be used to provide data to the databook. |
- | ==== DataBook, accessing data ==== | + | ==== Databook, Accessing Data ==== |
- | And now we are at the other end of the chain, at the DataBook on the client side. We just need to tell our DataBook what DataSource to use, and we are done. | + | And now we are at the other end of the chain,: at the databook on the client side. We just need to tell our databook what data source to use, and we are done. |
<code java> | <code java> | ||
Line 978: | Line 978: | ||
dataBook.open(); | dataBook.open(); | ||
</code> | </code> | ||
- | The name of the DataBook is used to access the DBStorage object in the LCO provided by the DataSource. The mechanism for that is a simple search for a getter with the set name. | + | The name of the databook is used to access the DBstorage object in the LCO provided by the data source. The mechanism for that is a simple search for a getter with the set name. |
===== Interactive Demo ===== | ===== Interactive Demo ===== | ||
- | [[https://blog.sibvisions.com/wp_content/uploads/2017/04/lifecycle_objects_demo.html|There is an interactive demo on our blog]] which allows you to explore the connections between the client and server side. The complement classes are always highlighted and you can click on the names of the objects to receive additional information about them. | + | [[https://blog.sibvisions.com/wp-content/uploads/2017/04/lifecycle-objects-demo.html|There is an interactive demo on our blog]] that allows you to explore the connections between the client- and server side. The complement classes are always highlighted, and you can click on the names of the objects to receive additional information. |
- | ===== The JVx application: Manual example ===== | + | ===== The JVx Application: Manual Example ===== |
- | Now that we have seen all layers that make up the architecture of [[https://sourceforge.net/projects/jvx/|JVx]], let us put all of that into code: | + | Now that we have seen all layers that make up the architecture of [[https://sourceforge.net/projects/jvx/|JVx]], let's put all of that into code: |
<code java> | <code java> | ||
Line 1061: | Line 1061: | ||
} | } | ||
</code> | </code> | ||
- | With this little example we have a completely working [[https://sourceforge.net/projects/jvx/|JVx]] application. We provide ways to create most of this out of the box and read most of it from configuration files, so there really is just little code to be written, see [[https://sourceforge.net/projects/jvxfirstapp/|the JVx FirstApp]] as a perfect example for that. So there is rarely any need to write code like this, all you have to do is create a new application and start it. | + | With this little example, we have a wholly working [[https://sourceforge.net/projects/jvx/|JVx]] application. We provide ways to create most of this out of the box and read most of it from configuration files, so there really is little code to be written. See [[https://sourceforge.net/projects/jvxfirstapp/|the JVx FirstApp]] as a perfect example of this.As you can see, there is rarely any need to write such code; all you have to do is create a new application and start it. |
- | Additionally, we could combine this long example with the simple one from before to initialize and create a GUI which could use our ''%%RemoteDataBook%%'', like this: | + | Additionally, we could combine this long example with the simple one from before to initialize and create a GUI that could use our ''%%RemoteDataBook%%'', like this: |
<code java> | <code java> | ||
Line 1081: | Line 1081: | ||
frame.eventWindowClosed().addListener(() -> System.exit(0)); | frame.eventWindowClosed().addListener(() -> System.exit(0)); | ||
</code> | </code> | ||
- | ===== Abstractions on every step ===== | + | ===== Abstractions at Every Step ===== |
- | As you can see, you always have full control over the framework and can always tailor it to your needs. There is always the possibility to provide a custom implementation to fulfill your needs: | + | As you can see, you always have full control over the framework and can always tailor it to your needs. There is always the possibility to provide a custom implementation: |
- | * Accessing a not supported database can be achieved by extending ''%%DBAccess%%''. | + | * Accessing an unsupported database can be achieved by extending ''%%DBAccess%%''. |
* Having a different service/way of providing data can be implemented on top of ''%%IStorage%%''. | * Having a different service/way of providing data can be implemented on top of ''%%IStorage%%''. | ||
* Supporting a different connection can be implemented on top of ''%%IConnection%%''. | * Supporting a different connection can be implemented on top of ''%%IConnection%%''. | ||
* And a completely different way of providing data can be implemented on top of ''%%IDataSource%%''. | * And a completely different way of providing data can be implemented on top of ''%%IDataSource%%''. | ||
- | You can swap out every layer and provide custom and customized implementations which exactly work as you require it. | + | You can swap out every layer and provide custom and customized implementations, which work exactly as you require. |
- | ===== Just like that ===== | + | ===== Just Like That ===== |
- | Just like that we’ve walked through the whole stack of a [[https://sourceforge.net/projects/jvx/|JVx]] application, from the database, which holds the data, all the way to the client GUI. Of course there is much more going on in a full-blown [[https://sourceforge.net/projects/jvx/|JVx]] application, for example I’ve spared you here the details of the configuration, server, network and providing actual LCOs and similar. But all in all, this should get you going. | + | Just like that, we’ve walked through the whole stack of a [[https://sourceforge.net/projects/jvx/|JVx]] application, from the database, which holds the data, all the way to the client GUI. Of course, there is much more going on in a full-blown [[https://sourceforge.net/projects/jvx/|JVx]] application. For example, I’ve spared you here the details of the configuration, server, network, and providing actual LCOs. However, all in all, this should get you going. |
====== CellEditors ====== | ====== CellEditors ====== | ||
- | Let’s talk about CellEditors, and how they are decoupled from the surrounding GUI. | + | Let’s talk about CellEditors and how they are decoupled from the surrounding GUI. |
- | ===== What are they? ===== | + | ===== What Are They? ===== |
- | While we’ve already covered large parts of [how the GUI layer](#of-technologies-and-factories] and [[#jvx|JVx]] works, the CellEditors have been left completely untouched and unmentioned. One might believe that they can be easily explained together with the Editors, however, they are a topic on their own, and a complex one from time to time that is. | + | While we’ve already covered large parts of how the GUI layer of technologies and factories and [[#jvx|JVx]] work, the CellEditors have been left completely untouched and unmentioned. One might believe that they can be easily explained together with the editors. However, they are a topic of their own -- and a complex one at that. |
- | The difference between Editors (the ''%%UIEditor%%'' for the most part) and CellEditors is that the Editors only provide the high-level GUI control, while the CellEditors provide the actual functionality. Let’s take a look at a quite simple screen. | + | The difference between editors (the ''%%UIEditor%%'' for the most part) and CellEditors is that the editors only provide the high-level GUI control, while the CellEditors provide the actual functionality. Let’s take a look at a simple screen. |
{{:jvx:reference:celleditors.png?nolink|The layout of a simple screen with a table and a few editors.}} | {{:jvx:reference:celleditors.png?nolink|The layout of a simple screen with a table and a few editors.}} | ||
- | We see a window with a table on the left and some editors on the right, simple enough. Now these components we are seeing are ''%%UIEditor%%''s, not CellEditors. The CellEditors themselves are only added as child components to the Editors, so the Editors are basically just panels which contain the actual CellEditor. | + | We see a window with a table on the left and some editors on the right, simple enough. Now these components we are seeing are ''%%UIEditor%%''s, not CellEditors. The CellEditors themselves are only added as child components to the editors, so the editors are basically just panels which contain the actual CellEditor. |
{{:jvx:reference:celleditors2.png?nolink|The same scree but with the CellEditors differentiated from the UIEditors which contain them.}} | {{:jvx:reference:celleditors2.png?nolink|The same scree but with the CellEditors differentiated from the UIEditors which contain them.}} | ||
- | So technically every ''%%UIEditor%%'' is just another panel which gets the CellEditor added. The CellEditors themselves follow the same pattern as all GUI components in [[https://sourceforge.net/projects/jvx/|JVx]], there is the base interface, an eventual extension of technology components, the implementation and finally the UI object. They are, however, rarely directly used in building the GUI, but mostly only referenced when building the model. | + | Technically, every ''%%UIEditor%%'' is just another panel that gets the CellEditor added. The CellEditors themselves follow the same pattern as all GUI components in [[https://sourceforge.net/projects/jvx/|JVx]]: there is the base interface, an eventual extension of technology components, the implementation, and, finally, the UI object. They are, however, rarely directly used in building the GUI but mostly only referenced when building the model. |
- | ===== Why are they? ===== | + | ===== Why Do They Exist? ===== |
- | If you want to make GUI editor components, I know of two possible ways from the top of my head to achieve that: You create dedicated editor components for the datatypes that are available, for example a NumberEditor, TextEditor and so forth. Or you create one editor component which acts as a mere container and allows to plug in any wanted behavior for the type you’re editing. | + | If you want to make GUI editor components, I know of two possible ways off the top of my head to achieve that: you create dedicated editor components for the datatypes that are available, for example a NumberEditor, TextEditor, and so forth, or you create one editor component that acts as a mere container and allows you to plug in any wanted behavior for the type you’re editing. |
- | We’ve opted for the second option, because it means that the GUI is actually decoupled from the datatypes (and in extension the data) of the model. If we’d have separate components for each datatype, changing the datatype of a single column would mean that you’d have to touch all editors associated with that column and change that code, maybe with rippling effects on the rest of the GUI. With the CellEditors, one can change the datatype of a column and not worry about the GUI that is associated with that column. The CellEditor is changed on the model once and that change is automatically picked up by all Editors. Which also means that one can define and change defaults very easily and globally. | + | We’ve opted for the second option because it means that the GUI is actually decoupled from the datatypes (and in extension the data) of the model. If we’d have separate components for each datatype, changing the datatype of a single column would mean that you’d have to touch all editors associated with that column and change that code, maybe with rippling effects on the rest of the GUI. With the CellEditors, one can change the datatype of a column and not worry about the GUI that is associated with that column. The CellEditor is changed on the model once and that change is automatically picked up by all editors. This also means that one can define and change defaults very easily and globally. |
- | Of course one can also set the preferred or wanted CellEditor directly on the Editor, instead of using the one defined in the model, should the need arise. | + | Of course, one can also set the preferred or wanted CellEditor directly on the editor instead of using the one defined in the model should the need arise. |
- | ===== And the table? ===== | + | ===== And the Table? ===== |
- | The same applies to the Table. Theoretically, every cell of the Table can be viewed as a single Editor, for this context at least. So a single cell behaves the same as an Editor when it comes to how the CellEditors are handled. | + | The same applies to the table. Theoretically, every cell of the table can be viewed as a single editor, for this context at least. So a single cell behaves the same as an editor when it comes to how the CellEditors are handled. |
- | ===== How many are there? ===== | + | ===== How Many Are There? ===== |
[[https://sourceforge.net/projects/jvx/|JVx]] comes with a variety of CellEditors out of the box: | [[https://sourceforge.net/projects/jvx/|JVx]] comes with a variety of CellEditors out of the box: | ||
Line 1141: | Line 1141: | ||
* Standard | * Standard | ||
- | With these nearly all needs can be covered. If there is need for a new one, it can be created and added like any other UI component. | + | With these, nearly all needs can be covered. If there is need for a new one, it can be created and added like any other UI component. |
===== Using CellEditors ===== | ===== Using CellEditors ===== | ||
- | As said previously, which CellEditor is used is defined primarily with the model, for example: | + | As said previously, which CellEditor is used is defined primarily with the model. For example: |
<code java> | <code java> | ||
Line 1169: | Line 1169: | ||
} | } | ||
</code> | </code> | ||
- | We can see that every column has a datatype and every datatype has a CellEditor. That allows the model to provide the actual editing functionality without changing the GUI code. The Editor, when ''%%notifyRepaint()%%'' is called, will fetch the CellEditor from the datatype and use it. Additionally, there is a technology dependent default mechanism which allows this system to work even when the UI classes are not used. | + | We can see that every column has a datatype and every datatype has a CellEditor. That allows the model to provide the actual editing functionality without changing the GUI code. The editor, when ''%%notifyRepaint()%%'' is called, will fetch the CellEditor from the datatype and use it. Additionally, there is a technology-dependent default mechanism that allows this system to work even when the UI classes are not used. |
- | Let’s do a step by step explanation of what happens: | + | Let’s do a step-by-step explanation of what happens: |
* The model is created. | * The model is created. | ||
* The GUI is created. | * The GUI is created. | ||
* The model invokes ''%%notifyRepaint()%%'' on all bound controls. | * The model invokes ''%%notifyRepaint()%%'' on all bound controls. | ||
- | * The Editor gets the CellEditor from the model and adds it to itself. | + | * The editor gets the CellEditor from the model and adds it to itself. |
- | ===== One moment, instance sharing? ===== | + | ===== Instance Sharing ===== |
- | If we revisit the example code from above, we will notice that the CellEditor instance is set on the model and must then be used by the Editor. That means that a single CellEditor instance is used for all bound Editors. We all know that sharing instances in such a way can be fun, but in this case it is not a problem because CellEditors are only “factories” for the actual editing components. | + | If we revisit the example code from above, we will notice that the CellEditor instance is set on the model and must then be used by the editor. That means that a single CellEditor instance is used for all bound editors. We all know that sharing instances in such a way can be fun, but, in this case, it is not a problem because CellEditors are only “factories” for the actual editing components. |
- | The ''%%ICellEditor%%'' interface does actually only specify two methods, whether it is a direct cell editor, and the factory method for creating an ''%%ICellEditorHandler%%''. The CellEditorHandler is the manager of the instance of the component that is going to be embedded into the Editor. | + | The ''%%ICellEditor%%'' interface actually only specifies two methods: whether or not it is a direct cell editor, and the factory method for creating an ''%%ICellEditorHandler%%''. The CellEditorHandler is the manager of the instance of the component that is going to be embedded into the editor. |
* ''%%notifyRepaint()%%'' is called on the editor. | * ''%%notifyRepaint()%%'' is called on the editor. | ||
Line 1190: | Line 1190: | ||
This mechanism makes sure that no component instances end up shared between different GUI components. | This mechanism makes sure that no component instances end up shared between different GUI components. | ||
- | ===== A closer look at the CellEditorHandler ===== | + | ===== A Closer Look at the CellEditorHandler ===== |
- | If we take a good look at the CellEditorHandler interface, we see that it contains everything that is required for setting up a component to be able to edit data coming from a DataRow. One method is especially important, the ''%%getCellEditorComponent()%%'' function. It returns the actual technology component that is to be embedded into the Editor. That means that even though there are implementations for the CellEditors on the UI layer, the actual components which will provide the functionality for editing the data are implemented on the technology layer. A short refresher: | + | If we take a good look at the CellEditorHandler interface, we see that it contains everything that is required for setting up a component to be able to edit data coming from a data row. One method is especially important: the ''%%getCellEditorComponent()%%'' function. It returns the actual technology component that is to be embedded into the editor. That means that, even though there are implementations for the CellEditors on the UI layer, the actual components that will provide the functionality for editing the data are implemented on the technology layer. A short refresher: |
- | {{:jvx:reference:layers.png?nolink|The different layers of , User, UI Wrappers, Implementations, Extensions and the Technology.}} | + | {{:jvx:reference:layers.png?nolink|The different layers of user, UI wrappers, implementations, extensions, and the technology.}} |
Revisiting our simple screen from above, we’d actually need to represent it as something like this: | Revisiting our simple screen from above, we’d actually need to represent it as something like this: | ||
- | {{:jvx:reference:celleditors3.png?nolink|The previous screen with changed colors to correctly represent the CellEditor as mix of Technology and Extension.}} | + | {{:jvx:reference:celleditors3.png?nolink|The previous screen with changed colors to correctly represent the CellEditor as a mix of technology and extension.}} |
- | Because the embedded components in the Editor are actually on the technology layer. | + | Because the embedded components in the editor are actually on the technology layer. |
===== CellRenderers ===== | ===== CellRenderers ===== | ||
- | There is another small topic we need to discuss, CellRenderers. They follow nearly the same schematics as CellEditors but are used to display values directly, for example values in a table cell. The Table is also the primary component which uses them to display the cell values until the editing is started. For simplicity reasons, most CellEditors implement ''%%ICellRenderer%%'' directly and provide management of the created component. That is because the reuse of components for barely displaying values is easier does not contain as much error potential. | + | There is another small topic we need to discuss, CellRenderers. They follow nearly the same schematics as CellEditors but are used to display values directly; for example, values in a table cell. The table is also the primary component that uses them to display the cell values until the editing is started. For simplicity's sake, most CellEditors implement ''%%ICellRenderer%%'' directly and provide management of the created component. That is because the reuse of components for barely displaying values is easier and doesn't have as much potential for error. |
===== Conclusion ===== | ===== Conclusion ===== | ||
- | CellEditors provide an easy mechanic to allow to edit data, and more important, they are decoupled from the GUI code in which they are used in a way which allows the model to change, even dynamically. That enables programmers to create and edit screens and models quickly without the need to check if the GUI and the model fit together, they always do. | + | CellEditors provide an easy way to edit data, and, more importantly, they are decoupled from the GUI code in which they are used in a way that allows the model to change, even dynamically. This enables programmers to create and edit screens and models quickly without the need to check if the GUI and the model fit together because they always will. |
- | ====== Custom components ====== | + | ====== Custom Components ====== |
Let’s talk about custom components, and how to create them. | Let’s talk about custom components, and how to create them. | ||
Line 1216: | Line 1216: | ||
===== The GUI of JVx ===== | ===== The GUI of JVx ===== | ||
- | We’ve previously covered how [[#the_gui_of_jvx_works|the GUI of JVx works]], and now we will have a look on how we can add custom components to the GUI. | + | We’ve previously covered how [[#the_gui_of_jvx_works|the GUI of JVx works]], and now we will have a look at how we can add custom components to the GUI. |
- | In the terminology of [[https://sourceforge.net/projects/jvx/|JVx]] there are two different kinds of custom components: | + | In the terminology of [[https://sourceforge.net/projects/jvx/|JVx]], there are two different kinds of custom components: |
* UI based | * UI based | ||
Line 1225: | Line 1225: | ||
We will look at both, of course. | We will look at both, of course. | ||
- | ===== Custom components at the UI layer ===== | + | ===== Custom Components at the UI Layer ===== |
- | The simplest way to create custom components is to extend and use already existing UI classes, like ''%%UIPanel%%'' or ''%%UIComponent%%''. These custom components will be Technology independent because they use Technology independent components, there is no need to know about the underlying Technology. You can think of those as a “remix” of already existing components. | + | The simplest way to create custom components is to extend and use already existing UI classes like ''%%UIPanel%%'' or ''%%UIComponent%%''. These custom components will be technology-independent because they use technology-independent components. There is no need to know about the underlying technology. You can think of them as a “remix” of already existing components. |
- | The upside is that you never have to deal with the underlying Technology, the downside is that you can only use already existing components (custom drawing is not possible, for example). | + | The upside is that you never have to deal with the underlying technology, but the downside is that you can only use already existing components (custom drawing is not possible). |
- | Let’s look at a very simple example, we will extend the ''%%UILabel%%'' to always display a certain postfix along with the set text: | + | Let’s look at a very simple example. Te will extend the ''%%UILabel%%'' to always display a certain postfix along with the set text: |
<code java> | <code java> | ||
Line 1301: | Line 1301: | ||
It will be treated just like another label, but every time a text is set, the postfix is appended to it. | It will be treated just like another label, but every time a text is set, the postfix is appended to it. | ||
- | Another example, we want a special type of component, one that always does the same but will be used in many different areas of the application, it should contain a label and two buttons. The best approach for a custom component which should not inherit any specific behavior is to extend ''%%UIComponent%%'': | + | Another example: we want a special type of component one that always does the same but will be used in many different areas of the application. It should contain a label and two buttons. The best approach for a custom component that should not inherit any specific behavior is to extend ''%%UIComponent%%'': |
<code java> | <code java> | ||
Line 1325: | Line 1325: | ||
} | } | ||
</code> | </code> | ||
- | So we extend ''%%UIComponent%%'' and set a new ''%%UIPanel%%'' as UIResource on it, which we can use later and which is the base for our new component. After that we added a label and two buttons which will play beep sounds if pressed. This component does not expose any specific behavior as it extends ''%%UIComponent%%'', it only inherits the most basic properties, like background color and font settings, yet it can easily be placed anywhere in the application and will perform its duty. | + | So we extend ''%%UIComponent%%'' and set a new ''%%UIPanel%%'' as UIResource on it, which we can use later and which is the base for our new component. After that, we added a label and two buttons which will play beep sounds if pressed. This component does not expose any specific behavior as it extends ''%%UIComponent%%''. It only inherits the most basic properties, like background color and font settings, yet it can easily be placed anywhere in the application and will perform its duty. |
- | ===== Custom controls at the Technology layer ===== | + | ===== Custom Controls at the Technology Layer ===== |
- | The more complex option is to create a custom component at the Technology layer. That means that we have to go through a multiple steps process to create and use the component: | + | The more complex option is to create a custom component at the technology layer. That means we have to go through a multi-step process to create and use the component: |
- Create an interface for the functionality you’d like to expose | - Create an interface for the functionality you’d like to expose | ||
- | - Extend the Technology component (if needed) | + | - Extend the technology component (if needed) |
- Implement the necessary interfaces for [[https://sourceforge.net/projects/jvx/|JVx]] | - Implement the necessary interfaces for [[https://sourceforge.net/projects/jvx/|JVx]] | ||
- Extend the factory to return the new component | - Extend the factory to return the new component | ||
Line 1338: | Line 1338: | ||
- Use the new factory | - Use the new factory | ||
- | I will walk you through this process, step by step. | + | I will walk you through this process step by step. |
- | The upside is that we can use any component which is available to us in the Technology, the downside is that it is quite some work to build the correct chain, ideally for every Technology. | + | The upside is that we can use any component that is available to us in the technology. The downside is that it is quite a bit of work to build the correct chain, ideally for every technology. |
- | ==== Creating an interface ==== | + | ==== Creating an Interface ==== |
- | The first step is to think about what functionality the component should expose, we will use a progress bar as example. We don’t want anything fancy for now, a simple progress bar on which we set a percent value should be more than enough: | + | The first step is to think about what functionality the component should expose. We will use a progress bar as an example. We don’t want anything fancy for now, a simple progress bar on which we set a percent value should be more than enough: |
<code java> | <code java> | ||
Line 1367: | Line 1367: | ||
} | } | ||
</code> | </code> | ||
- | Might not be the most sophisticated example (especially in regards to documentation) but it will do for now. This interface will be the foundation for our custom component. | + | It might not be the most sophisticated example (especially in regards to documentation), but it will do for now. This interface will be the foundation for our custom component. |
- | ==== Extending the component, if needed ==== | + | ==== Extending the Component, if Needed ==== |
- | We will be using Swing and the ''%%JProgressBar%%'' for this example, so the next step is to check if we must add additional functionality to the Technology component. In our case we don’t, as we do not demand any behavior that is not provided by ''%%JProgressBar%%'', but for the sake of the tutorial we will still create an extension of ''%%JProgressBar%%'' anyway. | + | We will be using Swing and the ''%%JProgressBar%%'' for this example, so the next step is to check if we must add additional functionality to the technology component. In our case we don’t, as we do not demand any behavior that is not provided by ''%%JProgressBar%%'', but, for the sake of the tutorial, we will still create an extension of ''%%JProgressBar%%''. |
<code java> | <code java> | ||
Line 1382: | Line 1382: | ||
} | } | ||
</code> | </code> | ||
- | Within this class we could now implement additional behavior independent of [[https://sourceforge.net/projects/jvx/|JVx]]. For example, we provide many extended components for Swing, JavaFX and Vaadin with additional features but without depending on [[https://sourceforge.net/projects/jvx/|JVx]]. The extension layer is the perfect place to extend already existing components with functionality which will be used by, but is not depending on, [[https://sourceforge.net/projects/jvx/|JVx]]. | + | Within this class, we could now implement additional behavior independent of [[https://sourceforge.net/projects/jvx/|JVx]]. For example, we provide many extended components for Swing, JavaFX, and Vaadin with additional features but without depending on [[https://sourceforge.net/projects/jvx/|JVx]]. The extension layer is the perfect place to extend already existing components with functionality that will be used by, but is not dependent on, [[https://sourceforge.net/projects/jvx/|JVx]]. |
==== Creating the Implementation ==== | ==== Creating the Implementation ==== | ||
- | The next step is to create an Implementation class which allows us to bind our newly extended ''%%JProgressBar%%'' to the [[https://sourceforge.net/projects/jvx/|JVx]] interfaces. Luckily there is the complete Swing Implementation infrastructure which we can use: | + | The next step is to create an implementation class that allows us to bind our newly extended ''%%JProgressBar%%'' to the [[https://sourceforge.net/projects/jvx/|JVx]] interfaces. Luckily, there is the complete Swing implementation infrastructure we can use: |
<code java> | <code java> | ||
Line 1412: | Line 1412: | ||
} | } | ||
</code> | </code> | ||
- | That’s it already. Again, in this case it is quite simple because we do not expect a lot of behavior. The implementation layer is the place to “glue” the component to the [[https://sourceforge.net/projects/jvx/|JVx]] interface, implementing missing functionality which is depending on [[https://sourceforge.net/projects/jvx/|JVx]] and “translating” and forwarding values and properties. | + | That’s it already. Again, in this case it is quite simple because we do not expect a lot of behavior. The implementation layer is the place to “glue” the component to the [[https://sourceforge.net/projects/jvx/|JVx]] interface, implementing missing functionality that is depending on [[https://sourceforge.net/projects/jvx/|JVx]] and “translating” and forwarding values and properties. |
- | ==== Extending the factory ==== | + | ==== Extending the Factory ==== |
- | Now we must extend the factory to be aware of our new custom component, that is equally simple as our previous steps. First we extend the interface: | + | Now, we must extend the factory to be aware of our new custom component, which is equally as simple as our previous steps. First, we extend the interface: |
<code java> | <code java> | ||
Line 1424: | Line 1424: | ||
} | } | ||
</code> | </code> | ||
- | And afterwards we extend the SwingFactory: | + | And then we extend the SwingFactory: |
<code java> | <code java> | ||
Line 1469: | Line 1469: | ||
} | } | ||
</code> | </code> | ||
- | Nearly done, we can nearly use our new and shiny component in our project. | + | Nearly done, we can almost use our new and shiny component in our project. |
- | ==== Using the custom factory ==== | + | ==== Using the Custom Factory ==== |
- | Of course we have to tell [[https://sourceforge.net/projects/jvx/|JVx]] that we want to use our factory, and not the default one. Depending on the technology which is used, this has to be done at different places. | + | Of course, we have to tell [[https://sourceforge.net/projects/jvx/|JVx]] that we want to use our factory and not the default one. Depending on the technology used, this is done at different places. |
=== Swing and JavaFX === | === Swing and JavaFX === | ||
Line 1492: | Line 1492: | ||
</init-param> | </init-param> | ||
</code> | </code> | ||
- | ==== Using our new component ==== | + | ==== Using Our New Component ==== |
- | And now we are done, from here we can use our custom component like any other. | + | Now we are done. From here we can use our custom component like any other. |
<code java> | <code java> | ||
Line 1504: | Line 1504: | ||
add(progressBar, constraints); | add(progressBar, constraints); | ||
</code> | </code> | ||
- | ===== Wrapping custom components with UICustomComponent ===== | + | ===== Wrapping Custom Components With UICustomComponent ===== |
- | There is a third way to have Technology dependent custom components in [[https://sourceforge.net/projects/jvx/|JVx]], you can wrap them within a ''%%UICustomComponent%%'': | + | There is a third way to have technology-dependent custom components in [[https://sourceforge.net/projects/jvx/|JVx]]. You can wrap them within a ''%%UICustomComponent%%'': |
<code java> | <code java> | ||
Line 1518: | Line 1518: | ||
add(customProgressBar, constraints); | add(customProgressBar, constraints); | ||
</code> | </code> | ||
- | This has the upside of being fast and easy, but the downside is that your code has to know about the currently used Technology and is not easily portable anymore. | + | This has the upside of being fast and easy, but the downside is that your code has to know about the currently used technology and it is no longer easily portable. |
===== Conclusion ===== | ===== Conclusion ===== | ||
- | As you can see, there are multiple ways of extending the default set of components which are provided by [[https://sourceforge.net/projects/jvx/|JVx]], depending on the use case and what custom components are required. It is very easy to extend [[https://sourceforge.net/projects/jvx/|JVx]] with all the components one does require. | + | As you can see, there are multiple ways of extending the default set of components that are provided by [[https://sourceforge.net/projects/jvx/|JVx]], depending on the use case and what custom components are required. It is very easy to extend [[https://sourceforge.net/projects/jvx/|JVx]] with all the components one requires. |
====== FormLayout ====== | ====== FormLayout ====== | ||
- | Let’s talk about the [[http://forum.sibvisions.com/viewtopic.php?f=11&t=167&p=219|FormLayout]], and why the anchor system makes it much more flexible than just a simple grid. | + | Let’s talk about the [[http://forum.sibvisions.com/viewtopic.php?f=11&t=167&p=219|FormLayout]] and why the anchor system makes it much more flexible than a simple grid. |
===== Basics ===== | ===== Basics ===== | ||
- | JVx comes with 5 layouts out of the box: | + | JVx comes with five layouts out of the box: |
* null/none/manual | * null/none/manual | ||
Line 1538: | Line 1537: | ||
* FormLayout | * FormLayout | ||
- | From these five the first four are easily explained, only the FormLayout needs some more information because it might not be as easy to grasp in the first moment than the others. | + | Of these five, the first four are easily explained. Only the FormLayout needs some more information because it might not be as easy to grasp off the bat as the others. |
- | The FormLayout uses a dependent anchor system. An Anchor in this context is a position inside the layout which is calculated from parent anchors and either the size of the component or a fixed value. So we can say there are two different types of Anchors inside the FormLayout which we are concerned about: | + | The FormLayout uses a dependent anchor system. An anchor in this context is a position inside the layout that is calculated from parent anchors and either the size of the component or a fixed value. So we can say there are two different types of anchors inside the FormLayout that we are concerned about: |
- | * AutoSize-Anchors, its position is calculated from the component assigned to it. | + | * Autosize anchors, its position is calculated from the component assigned to it. |
- | * Fixed-Anchors, its position is fixed. | + | * Fixed anchors, its position is fixed. |
- | Additionally, there are three special cases of Fixed-Anchors: | + | Additionally, there are three special cases of fixed anchors: |
- | * Border-Anchors, which surround the FormLayout at its border. | + | * Border anchors, which surround the FormLayout at its border. |
- | * Margin-Anchors, which are inset from the border by the defined value. | + | * Margin anchors, which are inset from the border by the defined value. |
- | * Gap-Anchors, which are added to create a gap between components. | + | * Gap anchors, which are added to create a gap between components. |
- | When it comes to calculating the position of an anchor, the position of the parent anchor is determined and then the value of the current anchor is added (which is either the size of a component or a fixed value). Simplified and in pseudo-code it can expressed like this: | + | When it comes to calculating the position of an anchor, the position of the parent anchor is determined, and then the value of the current anchor is added (which is either the size of a component or a fixed value). Simplified and in pseudo-code it can expressed like this: |
<code java> | <code java> | ||
Line 1575: | Line 1574: | ||
With this knowledge, we are nearly done with completely understanding the FormLayout. | With this knowledge, we are nearly done with completely understanding the FormLayout. | ||
- | ===== Creating constraints ===== | + | ===== Creating Constraints ===== |
Now, the second important part after the basics is knowing how the constraints are created. For example this: | Now, the second important part after the basics is knowing how the constraints are created. For example this: | ||
Line 1584: | Line 1583: | ||
{{:jvx:reference:formlayout-1.png?nolink|FormLayout with one added component.}} | {{:jvx:reference:formlayout-1.png?nolink|FormLayout with one added component.}} | ||
- | With the coordinates of ''%%0,0%%'', no new anchors are created but instead the component is attached to the top and left margin anchor. Two new AutoSize-Anchors (horizontally and vertically) are created and attached to the component. | + | With the coordinates of ''%%0,0%%'', no new anchors are created. Instead, the component is attached to the top and left margin anchor. Two new autosize anchors (horizontal and vertical) are created and attached to the component. |
- | If we now add a second component in the same row: | + | We now add a second component in the same row: |
<code java> | <code java> | ||
Line 1594: | Line 1593: | ||
{{:jvx:reference:formlayout-2.png?nolink|FormLayout with two added components.}} | {{:jvx:reference:formlayout-2.png?nolink|FormLayout with two added components.}} | ||
- | Because we are still on row ''%%0%%'' the component is attached to the top margin anchor and the previous AutoSize-Anchor for this row. Then, a new Gap-Anchor will be created which is attached to the trailing AutoSize-Anchor of the previous component. | + | Because we are still on row ''%%0%%'', the component is attached to the top margin anchor and the previous autosize anchor for this row. Then, a new gap anchor will be created, which is attached to the trailing autosize anchor of the previous component. |
- | We can of course also add items to the right and bottom: | + | We can, of course, also add items to the right and bottom: |
<code java> | <code java> | ||
Line 1605: | Line 1604: | ||
{{:jvx:reference:formlayout-3.png?nolink|FormLayout with three added components, one in the bottom right corner.}} | {{:jvx:reference:formlayout-3.png?nolink|FormLayout with three added components, one in the bottom right corner.}} | ||
- | What happens is the same as when adding a component at the coordinates ''%%0,0%%'', except that the reference is the lower right corner. The component is attached to the bottom and right margin anchors, with trialing AutoSize-Anchors. | + | What happens is the same as when adding a component at the coordinates ''%%0,0%%'', except that the reference is the lower right corner. The component is attached to the bottom and right margin anchors with trialing autosize anchors. |
- | Last but not least, we can add components which span between anchors: | + | Last but not least, we can add components that span anchors: |
<code java> | <code java> | ||
Line 1617: | Line 1616: | ||
{{:jvx:reference:formlayout-4.png?nolink|FormLayout with four added components, one stretched.}} | {{:jvx:reference:formlayout-4.png?nolink|FormLayout with four added components, one stretched.}} | ||
- | Again, the same logic applies as previously, with the notable exception that new Gap-Anchors are created for all four sides. That includes variants which span over anchors: | + | Again, the same logic as previously applies, with the notable exception that new gap anchors are created for all four sides. This includes variants that span anchors: |
<code java> | <code java> | ||
Line 1626: | Line 1625: | ||
{{:jvx:reference:formlayout-5.png?nolink|FormLayout with three added components, one of them spans multiple anchors.}} | {{:jvx:reference:formlayout-5.png?nolink|FormLayout with three added components, one of them spans multiple anchors.}} | ||
- | The component is horizontally attached to the left Margin-Anchor and additionally to the AutoSize-Anchor of the second column. The AutoSize- and Gap-Anchor of the first column are not ignored, they are not relevant to this case. | + | The component is horizontally attached to the left margin anchor and additionally to the autosize anchor of the second column. The autosize- and gap anchors of the first column are not ignored, but they are not relevant to this case. |
- | At this point it is important to note that spanning and stretched components are disregarded for the preferred size calculation of the layout. So whenever you span or stretch a component, it is not taken into account when the preferred size of the layout is calculated, which can lead to unexpected results. | + | At this point it is important to note that spanning and stretched components are disregarded for the preferred size calculation of the layout. Therefore, whenever you span or stretch a component, it is not taken into account when the preferred size of the layout is calculated, which can lead to unexpected results. |
- | ===== Interactive demo ===== | + | ===== Interactive Demo ===== |
- | Sometimes, however, it might not be obvious what anchors are created and how they are used. For this we have created a simple interactive demonstration application which allows to inspect the created anchors of a layout, the [[https://github.com/sibvisions/jvx.formlayout_visualization|JVx FormLayout Visualization]]. | + | Sometimes, however, it might not be obvious what anchors are created and how they are used. For this, we have created a simple interactive demonstration application that allows you to inspect the created anchors of a layout: the [[https://github.com/sibvisions/jvx.formlayout-visualization|JVx FormLayout Visualization]]. |
{{:jvx:reference:formlayout-visualization.png?nolink|FormLayout Visualization Demo}} | {{:jvx:reference:formlayout-visualization.png?nolink|FormLayout Visualization Demo}} | ||
- | On the left is the possibility to show and hide anchors together with the information about the currently highlighted anchor. On the right is a Lua scripting area which allows you to quickly and easily rebuild and test layouts. It utilizes the [[https://blog.sibvisions.com/2017/09/25/jvx_lua_proof_of_concept/|JVx-Lua bridge from a previous blog post]] and so any changes to the code are directly applied. | + | On the left is the possibility to show and hide anchors together with the information about the currently highlighted anchor. On the right is an Lua scripting area, which allows you to quickly and easily rebuild and test layouts. It utilizes the [[https://blog.sibvisions.com/2017/09/25/jvx-lua-proof-of-concept/|JVx-Lua bridge from a previous blog post]] and so any changes to the code are directly applied. |
- | ===== The most simple usage: Flow-like ===== | + | ===== The Simplest Usage: Flow-Like ===== |
- | Enough of the internals, let’s talk use-cases. The most simple use-case for the FormLayout can be a container which flows its contents in a line until a certain number of items is reach, at which it breaks into a new line. | + | Enough of the internals, let’s talk use-cases. The most simple use-case for the FormLayout can be a container which flows its contents in a line until a certain number of items is reach, at which point it breaks into a new line. |
{{:jvx:reference:formlayout-flow.png?nolink|FormLayout with a flow layout}} | {{:jvx:reference:formlayout-flow.png?nolink|FormLayout with a flow layout}} | ||
Line 1672: | Line 1671: | ||
panel:add(stub()); | panel:add(stub()); | ||
</code> | </code> | ||
- | ===== The obvious usage: Grid-like ===== | + | ===== The Most Obvious Usage: Grid-Like ===== |
- | The FormLayout can also be used to align components in a grid, and actually layout them in a grid-like fashion. | + | The FormLayout can also be used to align components in a grid and actually layout them in a grid-like fashion. |
{{:jvx:reference:formlayout-grid.png?nolink|FormLayout with a grid layout}} | {{:jvx:reference:formlayout-grid.png?nolink|FormLayout with a grid layout}} | ||
- | With the main difference being that the columns and rows are sized according to the components in it and not given a fixed slice of the width of the panel. | + | The main difference is that columns and rows are sized according to the components and not given a fixed-width portion of the panel. |
==== Java ==== | ==== Java ==== | ||
Line 1708: | Line 1707: | ||
panel:add(stub(), layout:getConstraints(-1, 2, -1, -1)); | panel:add(stub(), layout:getConstraints(-1, 2, -1, -1)); | ||
</code> | </code> | ||
- | ===== The advanced usage: Anchor Configuration ===== | + | ===== The More Advanced Usage: Anchor Configuration ===== |
- | Additionally, the FormLayout offers the possibility to manually set the anchor positions, for example when it is necessary to give the first elements a certain size. Together with the ability to span components, this allows to create complex and rich layouts. | + | Additionally, the FormLayout offers the possibility to manually set the anchor position (e.g., when it is necessary to give the first elements a certain size). Together with the ability to span components, this allows us to create complex and rich layouts. |
{{:jvx:reference:formlayout-anchorconfiguration.png?nolink|FormLayout with a set anchor configuration}} | {{:jvx:reference:formlayout-anchorconfiguration.png?nolink|FormLayout with a set anchor configuration}} | ||
Line 1750: | Line 1749: | ||
===== Conclusion ===== | ===== Conclusion ===== | ||
- | The [[https://sourceforge.net/projects/jvx/|JVx]] FormLayout allows to quickly and easily create complex, good looking and working layouts which are still flexible enough for the cases when a component is swapped, removed or added. It can be used in many different circumstances and is still easy enough to use to make sure that even beginners are able to create a basic layout within seconds. | + | The [[https://sourceforge.net/projects/jvx/|JVx]] FormLayout allows us to quickly and easily create complex, good looking, and functioning layouts that are still flexible enough for the cases when a component is swapped, removed, or added. It can be used in many different circumstances and is still easy enough to use to make sure that even beginners are able to create a basic layout within seconds. |
====== Events ====== | ====== Events ====== | ||
Line 1756: | Line 1755: | ||
Let’s talk about events and event handling in [[https://sourceforge.net/projects/jvx/|JVx]]. | Let’s talk about events and event handling in [[https://sourceforge.net/projects/jvx/|JVx]]. | ||
- | ===== What are events… ===== | + | ===== What Are Events… ===== |
- | Events are an [[https://en.wikipedia.org/wiki/Event_driven_programming|important mechanism no matter to what programming language or framework you turn to]]. It allows us to react on certain actions and “defer” actions until something triggered them. Such triggers can be anything, like a certain condition is hit in another thread, the user clicked a button or another action has finally finished. Long story short, you get notified that something happened, and that you can now do something. | + | Events are an [[https://en.wikipedia.org/wiki/Event-driven_programming|important mechanism no matter to what programming language or framework you turn to]]. They allow us to react on certain actions and “defer” actions until something triggers them. Such triggers can be anything: a certain condition is hit in another thread, the user clicked a button, or another action has finally finished. Long story short, you are notified that something happened and you can now do something further. |
- | ===== …and why do I need to handle them? ===== | + | ===== …And Why Do I Need to Handle Them? ===== |
- | Well, you can’t skip events, they are a cornerstone of [[https://sourceforge.net/projects/jvx/|JVx]]. Theoretically, you could use [[https://sourceforge.net/projects/jvx/|JVx]] without using any of its events, but you would not only miss out on a lot of functionality but also be unable to do anything useful. But don’t worry, understanding the event system is easy, using it even easier. | + | Well, you can’t skip events, they are a cornerstone of [[https://sourceforge.net/projects/jvx/|JVx]]. Theoretically, you could use [[https://sourceforge.net/projects/jvx/|JVx]] without any of its events, but you would not only miss out on a lot of functionality, but also be unable to do anything useful. But don’t worry, understanding the event system is easy and using it even easier. |
===== Terminology ===== | ===== Terminology ===== | ||
- | For [[https://sourceforge.net/projects/jvx/|JVx]] the following terminology applies: An event is a property of an object, you can register listeners on that event which will get invoked if the event is dispatched (fired). Every event consists of the ''%%EventHandler%%'' which allows to register, remove and manage the listeners and also dispatches the events, meaning invoking the listeners and notifying them that the event occurred. There is no single underlying listener interface. | + | For [[https://sourceforge.net/projects/jvx/|JVx]] the following terminology applies: an event is a property of an object. You can register listeners on that event that will get invoked if the event is dispatched (fired). Every event consists of the ''%%EventHandler%%'', which allows ypi to register, remove, and manage the listeners and also dispatches the events, meaning it invokes the listeners and notifies them that the event occurred. There is no single underlying listener interface. |
- | Within the [[https://sourceforge.net/projects/jvx/|JVx]] framework, every event-property of an object does start with the prefix “event” to make it easily searchable and identifiable. But enough dry talk, let’s get started. | + | Within the [[https://sourceforge.net/projects/jvx/|JVx]] framework, every event property of an object starts with the prefix “event” to make it easily searchable and identifiable. But enough dry talk, let’s get started. |
- | ===== Attaching listeners ===== | + | ===== Attaching Listeners ===== |
We will now look at all the ways on how to attach a listener to an event. | We will now look at all the ways on how to attach a listener to an event. | ||
Line 1776: | Line 1775: | ||
==== Class ==== | ==== Class ==== | ||
- | The easiest way to get notified of events is to attach a class (which is implementing the listener interface) to an event as listener, like this: | + | The easiest way to get notified of events is to attach a class (that is implementing the listener interface) to an event as listener, like this: |
<code java> | <code java> | ||
Line 1801: | Line 1800: | ||
} | } | ||
</code> | </code> | ||
- | ==== Inlined class ==== | + | ==== Inlined Class ==== |
- | Of course we can inline this listener class: | + | Of course, we can inline this listener class: |
<code java> | <code java> | ||
Line 1977: | Line 1976: | ||
Now every time the event is dispatched, the ''%%somethingOtherHappened%%'' method will be invoked. Anyway, don’t use this. The upside of having a “simple” listener interface with just one method is that it allows to use lambdas with it. A listener interface with multiple methods won’t allow this. | Now every time the event is dispatched, the ''%%somethingOtherHappened%%'' method will be invoked. Anyway, don’t use this. The upside of having a “simple” listener interface with just one method is that it allows to use lambdas with it. A listener interface with multiple methods won’t allow this. | ||
- | In [[https://sourceforge.net/projects/jvx/|JVx]] [[http://blog.sibvisions.com/2015/01/28/jvx_and_java_8_events_and_lambdas/|we reduced our listener interfaces to just one method (in a backward compatible way)]] to make sure all events can be used with lambdas. | + | In [[https://sourceforge.net/projects/jvx/|JVx]] [[http://blog.sibvisions.com/2015/01/28/jvx-and-java-8-events-and-lambdas/|we reduced our listener interfaces to just one method (in a backward compatible way)]] to make sure all events can be used with lambdas. |
===== Fire away! ===== | ===== Fire away! ===== |