001package org.nasdanika.html.model.app.graph;
002
003import java.util.Collection;
004
005import org.eclipse.emf.common.util.URI;
006import org.eclipse.emf.ecore.EClass;
007import org.nasdanika.common.ProgressMonitor;
008import org.nasdanika.common.Supplier;
009import org.nasdanika.graph.Connection;
010import org.nasdanika.graph.emf.EClassConnection;
011import org.nasdanika.html.model.app.Label;
012import org.nasdanika.html.model.app.graph.emf.EObjectNodeProcessor;
013
014/**
015 * Creates labels, links for cross-referencing, and other "widgets".
016 * @author Pavel
017 *
018 */
019public interface WidgetFactory {
020        
021        /**
022         * Functional interface for selectors to which factories delegate widget creation.
023         * {@link Connection} {@link WidgetFactory} shall not delegate to Selector, but rather to ConnectionSelector 
024         */
025        interface Selector<T> {
026        
027                /**
028                 * Retrieves some information from the argument widget factory, e.g. creates a widget.   
029                 * @param widgetFactory
030                 * @param base For connections, if not null, is resolved against the calling end URI - source or target, if it is not null. 
031                 * If null, the respective end URI is used as the base.
032                 * @param progressMonitor
033                 * @return A widget or null
034                 */             
035                T select(WidgetFactory widgetFactory, URI base, ProgressMonitor progressMonitor); 
036                
037        }
038        
039        /**
040         * A maker interface indicating that {@link Connection} {@link WidgetFactory} shall delegate to this selector instead of passing it to the other end's node.
041         * @param <T>
042         */
043        interface ConnectionSelector<T> extends Selector<T> {
044                
045        }
046        
047        /**
048         * Creates a "label" which is an HTML/text representation of something which does not navigate to that something. E.g. {@link Label}. Can be composite.
049         * @return
050         */
051        Object createLabel(ProgressMonitor progressMonitor);
052        
053        /**
054         * Creates a string (HTML text) representation of "label".
055         * @return
056         */
057        String createLabelString(ProgressMonitor progressMonitor);
058        
059        /**
060         * Creates a link if possible or a label.
061         * Calls createLink(null, progressMonitor) 
062         * @return
063         */
064        default Object createLink(ProgressMonitor progressMonitor) {
065                return createLink(null, progressMonitor);
066        }
067        
068        /**
069         * Creates a link with URL's deresolved (relativized) against the provided base URI.
070         * 
071         * @param base For connections, if not null, is resolved against the calling end URI - source or target, if it is not null. 
072         * If null, the respective end URI is used as the base.
073         * @param progressMonitor
074         * @return
075         */
076        Object createLink(URI base, ProgressMonitor progressMonitor);
077        
078        /**
079         * Creates a help decorator.
080         * Calls createHelpDecorator(null, progressMonitor) 
081         * @return
082         */
083        default Label createHelpDecorator(ProgressMonitor progressMonitor) {
084                return createHelpDecorator(null, progressMonitor);
085        }
086        
087        /**
088         * Creates a help decorator with URL's deresolved (relativized) against the provided base URI.
089         * For example, an {@link EObjectNodeProcessor} for an object of type X would call its {@link EClassConnection} outgoing connection to create a help decorator. 
090         * The EClassConnection would in turn call EClassNodeProcessor for {@link EClass} X to generate context help decorator.  
091         * 
092         * @param base For connections, if not null, is resolved against the calling end URI - source or target, if it is not null. 
093         * If null, the respective end URI is used as the base.
094         * @param progressMonitor
095         * @return
096         */
097        Label createHelpDecorator(URI base, ProgressMonitor progressMonitor);
098        
099        /**
100         * Link rendered to String
101         * @param progressMonitor
102         * @return
103         */
104        default String createLinkString(ProgressMonitor progressMonitor) {
105                return createLinkString(null, progressMonitor);
106        }
107        
108        /**
109         * Link rendered to String
110         * @param base
111         * @param progressMonitor
112         * @return
113         */
114        String createLinkString(URI base, ProgressMonitor progressMonitor);
115        
116        /**
117         * Calls createWidget(selector, null, progressMonitor).
118         * For connections URL's in the link are deresolved (relativized) against the calling end URI - source or target, if it is not null.
119         * @param selector
120         * @param progressMonitor
121         * @return
122         */
123        default Object select(Object selector, ProgressMonitor progressMonitor) {
124                return select(selector, null, progressMonitor);
125        }
126
127        /**
128         * Creates a widget for an aspect (feature) of the object identified by the selector, which can be a {@link Selector}.   
129         * @param selector Aspect/feature key. If an instasnce of Selector, then the factory delegates widget creation to the selector passing itself as an argument.
130         * @param base For connections, if not null, is resolved against the calling end URI - source or target, if it is not null. 
131         * If null, the respective end URI is used as the base.
132         * @param progressMonitor
133         * @return A widget or null
134         */
135        default Object select(Object selector, URI base, ProgressMonitor progressMonitor) {
136                if (selector instanceof Selector) {
137                        return select((Selector<?>) selector, base, progressMonitor);
138                }
139                return null;
140        }
141        
142        default <T> T select(Selector<T> selector, URI base, ProgressMonitor progressMonitor) {
143                return selector.select(this, base, progressMonitor);
144        }       
145        
146        default <T> T select(Selector<T> selector, ProgressMonitor progressMonitor) {
147                return select(selector, null, progressMonitor);
148        }       
149
150        /**
151         * Calls createWidgetString(selector, null, progressMonitor)
152         * @param selector
153         * @param progressMonitor
154         * @return
155         */
156        default String selectString(Object selector, ProgressMonitor progressMonitor) {
157                return selectString(selector, null, progressMonitor);
158        }
159
160        /**
161         * @param selector
162         * @param base
163         * @param progressMonitor
164         * @return widget rendered to (HTML) string
165         */
166        String selectString(Object selector, URI base, ProgressMonitor progressMonitor);
167        
168        /**
169         * Used to establish node URI's. Propagates caller URI.
170         * @param base
171         */
172        void resolve(URI base, ProgressMonitor progressMonitor);
173        
174        Supplier<Collection<Label>> createLabelsSupplier();
175        
176        /**
177         * Configures a label for a given source object. This method allows multiple widget factories 
178         * collaborate on label/action configuration. E.g. the primary WidgetFactory may delegate to "facet" factories.  
179         * @param source
180         * @param label
181         * @param progressMonitor
182         */
183        default void configureLabel(Object source, Label label, ProgressMonitor progressMonitor) {
184                
185        }
186
187}