/** * Binds the provided component to the specified property (or property chain) of the model instance associated with * this proxy (see {@link DataBinder#setModel(Object, StateSync)}). * * @param component * the UI component to bind to, must not be null. * @param property * the property of the model to bind the widget to, must not be null. * @param converter * the converter to use for this binding, null if default conversion should be used. See * {@link Convert#getConverter(Class, Class)} and {@link Convert#identityConverter(Class)} for possible * arguments. * @return binding the created binding. */ public Binding bind(final Object component, final String property, final Converter converter) { return bind(component, property, converter, false, StateSync.FROM_MODEL); }
public void clearModelHandlers() { for (final HandlerRegistration reg : modelChangeHandlers) { reg.removeHandler(); } modelChangeHandlers.clear(); for (final DataBinder<?> binder : binders.values()) { getAgent(binder).clearModelHandlers(); } }
public MapBindableProxy( final Map<String, PropertyType> propertyTypes ) { agent = new BindableProxyAgent<>(this, new HashMap<>()); agent.propertyTypes.putAll(propertyTypes); agent .propertyTypes .entrySet() .stream() .filter(entry -> entry.getValue() instanceof MapPropertyType) .forEach(entry -> agent.binders.put(entry.getKey(), DataBinder.forMap(((MapPropertyType) entry.getValue()).getPropertyTypes()))); }
private static Supplier<Map<Class<? extends GwtEvent>, HandlerRegistration>> mergeNativeChangeEventListener( final Object component, final Optional<Supplier<Object>> uiGetter, final Consumer<Object> modelUpdater, Supplier<Map<Class<? extends GwtEvent>, HandlerRegistration>> registrar) { registrar = mergeToLeft(registrar, () -> { logger.debug("Adding native change event listener to {}", component); final JavaScriptObject listener = wrap(() -> uiGetter.ifPresent(getter -> modelUpdater.accept(getter.get()))); addChangeEventListener(component, listener); final HandlerRegistration hr = () -> removeChangeEventListener(component, listener); return Collections.singletonMap(ValueChangeEvent.class, hr); }); return registrar; }
private Binding createBinding(final Object component, final String property, final Converter converter, final Supplier<Map<Class<? extends GwtEvent>, HandlerRegistration>> handlerRegistrar) { final Binding binding = new Binding(property, component, converter, handlerRegistrar.get()); bindings.put(property, binding); if (propertyTypes.get(property).isList()) { if ("this".equals(property) && proxy instanceof BindableListWrapper) { addHandlersForBindableListWrapper("this", (BindableListWrapper) proxy); } else { proxy.set(property, ensureBoundListIsProxied(property)); } } return binding; }
newProxy.getBindableProxyAgent().mergePropertyChangeHandlers(propertyChangeHandlerSupport); if (fireChangeEvents) { newProxy.getBindableProxyAgent().fireChangeEvents(getAgent(), initialState); newProxy.getBindableProxyAgent().unbind(b); bindings.put(b.getProperty(), newProxy.getBindableProxyAgent() .bind(b.getComponent(), b.getProperty(), b.getConverter(), bindOnKeyUp, newInitState));
logger.debug("Binding property {} to component {}", property, component); final Converter converter = findConverter(property, getPropertyType(property).getType(), component, providedConverter); logger.debug("Using converter: {} <--> {}", converter.getModelType().getSimpleName(), converter.getComponentType().getSimpleName()); final Optional<Supplier<Object>> uiGetter = maybeCreateUIGetter(component); final Function<BindableProxyAgent<?>, Supplier<Map<Class<? extends GwtEvent>, HandlerRegistration>>> registrar = agent -> addHandlers(component, bindOnKeyUp, uiGetter, modelUpdater(component, converter, lastSubProperty, agent)); return bindHelper(component, property, converter, registrar, uiGetter, initialState);
@Override public <P> PropertyChangeUnsubscribeHandle addPropertyChangeHandler(final String property, final PropertyChangeHandler<P> handler) { propertyChangeHandlerSupport.addPropertyChangeHandler(property, handler); final PropertyChangeUnsubscribeHandle agentUnsubHandle = getAgent().addPropertyChangeHandler(property, handler); return new OneTimeUnsubscribeHandle() { @Override public void doUnsubscribe() { agentUnsubHandle.unsubscribe(); } }; }
/** * Unbinds all widgets bound to the specified model property by previous calls * to {@link #bind(HasValue, Object, String)}. This method has no effect if * the specified property was never bound. * * @param property * The name of the property (or a property chain) to unbind, Must not * be null. * * @return the same {@link DataBinder} instance to support call chaining. * @throws InvalidPropertyExpressionException * If the provided property chain expression is invalid. */ public DataBinder<T> unbind(final String property) { for (final Binding binding : bindings.get(property)) { getAgent().unbind(binding); } bindings.removeAll(property); if (bindings.isEmpty()) { // Proxies without bindings will be removed from the cache to make sure // the garbage collector can do its job (see // BindableProxyFactory#removeCachedProxyForModel). We throw away the // reference to the proxy to force a new lookup in case this data binder // will be reused. unwrapProxy(); } return this; }
/** * Unbinds the property with the given name. * * @param binding * the name of the model property to unbind, must not be null. */ public void unbind(final Binding binding) { final String property = binding.getProperty(); validatePropertyExpr(property); final int dotPos = property.indexOf("."); if (dotPos > 0) { final String bindableProperty = property.substring(0, dotPos); final DataBinder binder = binders.get(bindableProperty); if (binder != null) { final BindableProxyAgent<T> nestedAgent = ((BindableProxy<T>) binder.getModel()).getBindableProxyAgent(); final Collection<Binding> nestedBindings = nestedAgent.bindings.get(property.substring(dotPos + 1)); for (final Binding nestedBinding : nestedBindings.toArray(new Binding[nestedBindings.size()])) { if (binding.getComponent() == nestedBinding.getComponent()) { nestedAgent.unbind(nestedBinding); } } } } binding.removeHandlers(); bindings.remove(property, binding); if (bindings.isEmpty()) { BindableProxyFactory.removeCachedProxyForModel(target); } }
final BindableProxyAgent nestedAgent = ((BindableProxy<T>) nestedBinder.getModel()).getBindableProxyAgent(); final BindableProxyAgent otherNestedAgent = ((BindableProxy<T>) otherNestedBinder.getModel()).getBindableProxyAgent(); nestedAgent.fireChangeEvents(otherNestedAgent, state); maybeFirePropertyChangeEvent(property, oldValue, curValue);
private void clearModelHandlers() { getAgent().clearModelHandlers(); }
/** * Ensures that the given list property is wrapped in a * {@link BindableListWrapper}, so changes to the list become observable. * * @param property * the name of the list property * @param list * the list that needs to be proxied * * @return a new the wrapped (proxied) list or the provided list if already * proxied */ List ensureBoundListIsProxied(final String property, final List list) { if (!(list instanceof BindableListWrapper) && bindings.containsKey(property) && list != null) { final BindableListWrapper newList = new BindableListWrapper(list); addHandlersForBindableListWrapper(property, newList); return newList; } return list; }
newProxy.getBindableProxyAgent().mergePropertyChangeHandlers(propertyChangeHandlerSupport); if (fireChangeEvents) { newProxy.getBindableProxyAgent().fireChangeEvents(getAgent(), initialState); newProxy.getBindableProxyAgent().unbind(b); bindings.put(b.getProperty(), newProxy.getBindableProxyAgent() .bind(b.getComponent(), b.getProperty(), b.getConverter(), bindOnKeyUp, newInitState));
logger.debug("Binding property {} to component {}", property, component); final Converter converter = findConverter(property, getPropertyType(property).getType(), component, providedConverter); logger.debug("Using converter: {} <--> {}", converter.getModelType().getSimpleName(), converter.getComponentType().getSimpleName()); final Optional<Supplier<Object>> uiGetter = maybeCreateUIGetter(component); final Function<BindableProxyAgent<?>, Supplier<Map<Class<? extends GwtEvent>, HandlerRegistration>>> registrar = agent -> addHandlers(component, bindOnKeyUp, uiGetter, modelUpdater(component, converter, lastSubProperty, agent)); return bindHelper(component, property, converter, registrar, uiGetter, initialState);
@Override public PropertyChangeUnsubscribeHandle addPropertyChangeHandler(final PropertyChangeHandler<?> handler) { propertyChangeHandlerSupport.addPropertyChangeHandler(handler); final PropertyChangeUnsubscribeHandle agentUnsubHandle = getAgent().addPropertyChangeHandler(handler); return new OneTimeUnsubscribeHandle() { @Override public void doUnsubscribe() { agentUnsubHandle.unsubscribe(); } }; }
private static Supplier<Map<Class<? extends GwtEvent>, HandlerRegistration>> mergeNativeChangeEventListener( final Object component, final Optional<Supplier<Object>> uiGetter, final Consumer<Object> modelUpdater, Supplier<Map<Class<? extends GwtEvent>, HandlerRegistration>> registrar) { registrar = mergeToLeft(registrar, () -> { logger.debug("Adding native change event listener to {}", component); final JavaScriptObject listener = wrap(() -> uiGetter.ifPresent(getter -> modelUpdater.accept(getter.get()))); addChangeEventListener(component, listener); final HandlerRegistration hr = () -> removeChangeEventListener(component, listener); return Collections.singletonMap(ValueChangeEvent.class, hr); }); return registrar; }
/** * Unbinds all widgets bound to the specified model property by previous calls * to {@link #bind(HasValue, Object, String)}. This method has no effect if * the specified property was never bound. * * @param property * The name of the property (or a property chain) to unbind, Must not * be null. * * @return the same {@link DataBinder} instance to support call chaining. * @throws InvalidPropertyExpressionException * If the provided property chain expression is invalid. */ public DataBinder<T> unbind(final String property) { for (final Binding binding : bindings.get(property)) { getAgent().unbind(binding); } bindings.removeAll(property); if (bindings.isEmpty()) { // Proxies without bindings will be removed from the cache to make sure // the garbage collector can do its job (see // BindableProxyFactory#removeCachedProxyForModel). We throw away the // reference to the proxy to force a new lookup in case this data binder // will be reused. unwrapProxy(); } return this; }
/** * Unbinds the property with the given name. * * @param binding * the name of the model property to unbind, must not be null. */ public void unbind(final Binding binding) { final String property = binding.getProperty(); validatePropertyExpr(property); final int dotPos = property.indexOf("."); if (dotPos > 0) { final String bindableProperty = property.substring(0, dotPos); final DataBinder binder = binders.get(bindableProperty); if (binder != null) { final BindableProxyAgent<T> nestedAgent = ((BindableProxy<T>) binder.getModel()).getBindableProxyAgent(); final Collection<Binding> nestedBindings = nestedAgent.bindings.get(property.substring(dotPos + 1)); for (final Binding nestedBinding : nestedBindings.toArray(new Binding[nestedBindings.size()])) { if (binding.getComponent() == nestedBinding.getComponent()) { nestedAgent.unbind(nestedBinding); } } } } binding.removeHandlers(); bindings.remove(property, binding); if (bindings.isEmpty()) { BindableProxyFactory.removeCachedProxyForModel(target); } }
final BindableProxyAgent nestedAgent = ((BindableProxy<T>) nestedBinder.getModel()).getBindableProxyAgent(); final BindableProxyAgent otherNestedAgent = ((BindableProxy<T>) otherNestedBinder.getModel()).getBindableProxyAgent(); nestedAgent.fireChangeEvents(otherNestedAgent, state); maybeFirePropertyChangeEvent(property, oldValue, curValue);