All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.jsimpledb.vaadin.app.ReferenceFieldField Maven / Gradle / Ivy


/*
 * Copyright (C) 2015 Archie L. Cobbs. All rights reserved.
 */

package org.jsimpledb.vaadin.app;

import com.google.common.base.Preconditions;
import com.vaadin.data.Property;
import com.vaadin.server.Sizeable;
import com.vaadin.shared.ui.label.ContentMode;
import com.vaadin.ui.Alignment;
import com.vaadin.ui.Button;
import com.vaadin.ui.Component;
import com.vaadin.ui.CustomField;
import com.vaadin.ui.HorizontalLayout;
import com.vaadin.ui.HorizontalSplitPanel;
import com.vaadin.ui.Label;
import com.vaadin.ui.Notification;
import com.vaadin.ui.VerticalLayout;

import org.dellroad.stuff.spring.RetryTransaction;
import org.jsimpledb.CopyState;
import org.jsimpledb.JObject;
import org.jsimpledb.JTransaction;
import org.jsimpledb.core.ObjId;
import org.jsimpledb.parse.ParseSession;
import org.jsimpledb.vaadin.ConfirmWindow;
import org.jsimpledb.vaadin.JObjectChooser;
import org.jsimpledb.vaadin.JObjectContainer;
import org.jsimpledb.vaadin.SizedLabel;
import org.jsimpledb.vaadin.SmallButton;

/**
 * A Vaadin {@link com.vaadin.ui.Field} that edits a database object reference. Supports displaying,
 * but not selecting, a null value; wrap in a {@link org.jsimpledb.vaadin.NullableField} to allow for that.
 */
@SuppressWarnings("serial")
public class ReferenceFieldField extends CustomField {

    private final JTransaction dest;
    private final HorizontalLayout layout = new HorizontalLayout();
    private final ParseSession session;
    private final String name;
    private final Class type;
    private final JObjectContainer.RefLabelPropertyDef refLabelPropertyDef = new JObjectContainer.RefLabelPropertyDef();
    private final SmallButton changeButton = new SmallButton("Change...", new Button.ClickListener() {
        @Override
        public void buttonClick(Button.ClickEvent event) {
            ReferenceFieldField.this.change();
        }
    });

    private Component refLabel = new Label();

    /**
     * Constructor.
     *
     * @param dest target transaction for the chosen {@link JObject}
     * @param session session for expression parsing
     * @param name name of the property
     * @param type type restriction, or null for none
     */
    public ReferenceFieldField(JTransaction dest, ParseSession session, String name, Class type) {

        // Initialize
        Preconditions.checkArgument(dest != null, "null dest");
        Preconditions.checkArgument(session != null, "null session");
        Preconditions.checkArgument(name != null, "null name");
        this.dest = dest;
        this.session = session;
        this.name = name;
        this.type = type;

        // Listen for property value and read-only status changes
        this.addValueChangeListener(new Property.ValueChangeListener() {
            @Override
            public void valueChange(Property.ValueChangeEvent event) {
                ReferenceFieldField.this.updateDisplay();
            }
        });
        this.addReadOnlyStatusChangeListener(new Property.ReadOnlyStatusChangeListener() {
            @Override
            public void readOnlyStatusChange(Property.ReadOnlyStatusChangeEvent event) {
                ReferenceFieldField.this.updateDisplay();
            }
        });
    }

// CustomField

    @Override
    public Class getType() {
        return JObject.class;
    }

    @Override
    protected HorizontalLayout initContent() {
        this.layout.setMargin(false);
        this.layout.setSpacing(true);
        this.layout.addComponent(this.refLabel);
        this.layout.addComponent(new Label("\u00a0\u00a0"));
        this.layout.addComponent(this.changeButton);
        this.layout.setComponentAlignment(this.changeButton, Alignment.MIDDLE_LEFT);
        this.updateDisplay();
        return this.layout;
    }

    @Override
    protected void setInternalValue(JObject jobj) {
        super.setInternalValue(jobj);
        this.updateDisplay();
    }

// Internal methods

    // Update components to reflect new value
    private void updateDisplay() {
        final JObject jobj = this.getValue();
        final boolean readOnly = this.isReadOnly();
        final Component newLabel = jobj != null ?
          this.refLabelPropertyDef.extract(jobj) : new SizedLabel("Null ", ContentMode.HTML);
        this.layout.replaceComponent(this.refLabel, newLabel);
        this.refLabel = newLabel;
        this.changeButton.setEnabled(!readOnly);
    }

    // Handle change button click
    private void change() {
        this.new ChangeWindow().show();
    }

// ChangeWindow

    public class ChangeWindow extends ConfirmWindow {

        private final JObjectChooser objectChooser;

        ChangeWindow() {
            super(ReferenceFieldField.this.getUI(), "Select " + ReferenceFieldField.this.name);
            this.setWidth(800, Sizeable.Unit.PIXELS);
            this.setHeight(500, Sizeable.Unit.PIXELS);
            this.objectChooser = new JObjectChooser(ReferenceFieldField.this.session, ReferenceFieldField.this.type, false);
        }

        @Override
        protected void addContent(VerticalLayout layout) {
            final HorizontalSplitPanel objectPanel = this.objectChooser.getObjectPanel();
            objectPanel.setHeight(200, Sizeable.Unit.PIXELS);
            objectPanel.setSplitPosition(40);
            layout.addComponent(objectPanel);
            layout.addComponent(this.objectChooser.getShowForm());
        }

        @Override
        @RetryTransaction
        @org.springframework.transaction.annotation.Transactional("jsimpledbGuiTransactionManager")
        protected boolean execute() {
            final ObjId id = this.objectChooser.getObjId();
            if (id == null)
                return true;
            final JObject jobj = JTransaction.getCurrent().get(id);
            if (!jobj.exists()) {
                Notification.show("Object " + id + " no longer exists", null, Notification.Type.WARNING_MESSAGE);
                return false;
            }
            try {
                ReferenceFieldField.this.setValue(jobj.copyTo(ReferenceFieldField.this.dest, id, new CopyState()));
            } catch (Exception e) {
                Notification.show("Error: " + e, null, Notification.Type.ERROR_MESSAGE);
            }
            return true;
        }
    }
}





© 2015 - 2025 Weber Informatics LLC | Privacy Policy