commit cd29f770bb8e87244b7a0646e3fc976c5bd333f9
Author: Andreas Kohlbecker <a.kohlbecker@bgbm.org>
Date:   Thu May 11 14:16:50 2017 +0200

    ref #6612 Custom Textfield with switch for all protectable cache fields

diff --git a/pom.xml b/pom.xml
index dfaded2f..a11f1cf6 100755
--- a/pom.xml
+++ b/pom.xml
@@ -450,6 +450,16 @@
       <artifactId>contextmenu</artifactId>
       <version>4.5</version>
     </dependency>
+    <dependency>
+       <groupId>org.vaadin.teemu</groupId>
+       <artifactId>switch</artifactId>
+       <version>3.0.0</version>
+    </dependency>
+    <dependency>
+       <groupId>com.vaadin.addon</groupId>
+       <artifactId>vaadin-onoffswitch</artifactId>
+       <version>0.0.1</version>
+    </dependency>
 <!--     <dependency>
         only in the edit repo
       <groupId>org.vaadin.addons</groupId>
diff --git a/src/main/java/eu/etaxonomy/cdm/vaadin/AppWidgetSet.gwt.xml b/src/main/java/eu/etaxonomy/cdm/vaadin/AppWidgetSet.gwt.xml
index d20cdd82..566f8c47 100644
--- a/src/main/java/eu/etaxonomy/cdm/vaadin/AppWidgetSet.gwt.xml
+++ b/src/main/java/eu/etaxonomy/cdm/vaadin/AppWidgetSet.gwt.xml
@@ -40,4 +40,8 @@
     
 
     
+
+    <inherits name="org.vaadin.teemu.switchui.SwitchComponentWidgetset" />
+
+    <inherits name="com.vaadin.addon.onoffswitch.WidgetSet" />
 </module>
diff --git a/src/main/java/eu/etaxonomy/cdm/vaadin/component/TimePeriodField.java b/src/main/java/eu/etaxonomy/cdm/vaadin/component/TimePeriodField.java
deleted file mode 100644
index 6e541429..00000000
--- a/src/main/java/eu/etaxonomy/cdm/vaadin/component/TimePeriodField.java
+++ /dev/null
@@ -1,271 +0,0 @@
-/**
-* Copyright (C) 2017 EDIT
-* European Distributed Institute of Taxonomy
-* http://www.e-taxonomy.eu
-*
-* The contents of this file are subject to the Mozilla Public License Version 1.1
-* See LICENSE.TXT at the top of this package for the full license terms.
-*/
-package eu.etaxonomy.cdm.vaadin.component;
-
-import java.util.HashSet;
-import java.util.Set;
-
-import com.vaadin.data.fieldgroup.BeanFieldGroup;
-import com.vaadin.data.fieldgroup.FieldGroup.CommitException;
-import com.vaadin.data.util.BeanItem;
-import com.vaadin.event.FieldEvents.TextChangeEvent;
-import com.vaadin.server.FontAwesome;
-import com.vaadin.ui.Alignment;
-import com.vaadin.ui.Button;
-import com.vaadin.ui.Component;
-import com.vaadin.ui.CssLayout;
-import com.vaadin.ui.CustomField;
-import com.vaadin.ui.GridLayout;
-import com.vaadin.ui.Label;
-import com.vaadin.ui.TextField;
-import com.vaadin.ui.themes.ValoTheme;
-
-import eu.etaxonomy.cdm.model.common.TimePeriod;
-import eu.etaxonomy.cdm.strategy.parser.TimePeriodParser;
-import eu.etaxonomy.cdm.vaadin.component.registration.RegistrationStyles;
-import eu.etaxonomy.cdm.vaadin.util.formatter.DateTimeFormat;
-import eu.etaxonomy.cdm.vaadin.util.formatter.TimePeriodFormatter;
-
-/**
- * @author a.kohlbecker
- * @since Apr 6, 2017
- *
- */
-public class TimePeriodField extends CustomField<TimePeriod> {
-
-    private static final long serialVersionUID = -7377778547595966252L;
-
-    private static final String PRIMARY_STYLE = "v-time-period-field";
-
-    private BeanFieldGroup<TimePeriod> fieldGroup = new BeanFieldGroup<>(TimePeriod.class);
-
-    TextField parseField = null;
-
-    TextField freeText = null;
-
-    Label toLabel = null;
-
-    GridLayout grid = new GridLayout(3, 4);
-
-    CssLayout detailsView = new CssLayout();
-
-    //TODO implement custom button textfield which does not require a gridLayout
-    GridLayout buttonTextField = new GridLayout(2, 1);
-    GridLayout simpleView = new GridLayout(2, 1);
-
-    TextField cacheField = new TextField();
-
-    Set<Component> styledComponents = new HashSet<>();
-
-    private TimePeriodFormatter timePeriodFormatter = new TimePeriodFormatter(DateTimeFormat.ISO8601_DATE);
-
-    /**
-     *
-     */
-    public TimePeriodField() {
-        super();
-
-    }
-
-    /**
-     * @param string
-     */
-    public TimePeriodField(String string) {
-        this();
-        setCaption(string);
-    }
-
-    /**
-     * {@inheritDoc}
-     */
-    @Override
-    protected Component initContent() {
-
-        super.setPrimaryStyleName(PRIMARY_STYLE);
-
-        CssLayout root = new CssLayout();
-
-        initSimpleView();
-        initDetailsView();
-
-        root.addComponent(simpleView);
-        root.addComponent(detailsView);
-
-        applyDefaultStyles();
-
-        showSimple();
-
-        return root;
-    }
-
-    /**
-     *
-     */
-    private void initSimpleView() {
-
-        Button showDetailsButton = new Button(FontAwesome.CALENDAR);
-        showDetailsButton.addClickListener(e -> showDetails());
-        cacheField.setWidth(353, Unit.PIXELS); // FIXME 100% does not work
-
-        simpleView.addStyleName(ValoTheme.LAYOUT_COMPONENT_GROUP);
-        simpleView.setWidth(100, Unit.PERCENTAGE);
-        simpleView.addComponent(showDetailsButton, 0, 0);
-        simpleView.addComponent(cacheField, 1, 0);
-        simpleView.setColumnExpandRatio(1, 0.9f);
-    }
-
-    /**
-     *
-     */
-    private void initDetailsView() {
-
-        parseField = new TextField();
-        // parseField.setWidth(100, Unit.PERCENTAGE);
-        parseField.setInputPrompt("This field will parse the entered time period");
-        parseField.addTextChangeListener(e -> parseInput(e));
-        parseField.setWidth(100, Unit.PERCENTAGE);
-
-        Button closeDetailsButton = new Button(FontAwesome.CLOSE);
-        closeDetailsButton.addClickListener(e -> {
-            try {
-                fieldGroup.commit();
-            } catch (CommitException e1) {
-                // TODO Auto-generated catch block
-                e1.printStackTrace();
-            }
-            updateCacheField();
-            showSimple();
-        });
-
-        buttonTextField.addStyleName(ValoTheme.LAYOUT_COMPONENT_GROUP);
-        buttonTextField.setWidth(100, Unit.PERCENTAGE);
-        buttonTextField.addComponent(closeDetailsButton, 0, 0);
-        buttonTextField.addComponent(parseField, 1, 0);
-        buttonTextField.setColumnExpandRatio(1, 1.0f);
-
-        PartialDateField startDate = new PartialDateField("Start");
-        startDate.setInputPrompt("dd.mm.yyyy");
-        PartialDateField endDate = new PartialDateField("End");
-        endDate.setInputPrompt("dd.mm.yyyy");
-        freeText = new TextField("FreeText");
-        freeText.setWidth(100, Unit.PERCENTAGE);
-
-        fieldGroup.bind(startDate, "start");
-        fieldGroup.bind(endDate, "end");
-        fieldGroup.bind(freeText, "freeText");
-
-        toLabel = new Label("\u2014"); // EM DASH : 0x2014
-
-        int row = 0;
-        grid.addComponent(buttonTextField, 0, row, 2, row);
-        row++;
-        grid.addComponent(startDate, 0, row);
-        grid.addComponent(toLabel, 1, row);
-        grid.setComponentAlignment(toLabel, Alignment.BOTTOM_CENTER);
-        grid.addComponent(endDate, 2, row);
-        row++;
-        grid.addComponent(freeText, 0, row, 2, row);
-
-        // apply the style of the container to all child components. E.g. make all tiny
-        addStyleName((getStyleName()));
-
-        detailsView.setStyleName("margin-wrapper");
-        detailsView.addComponent(grid);
-
-    }
-
-
-    /**
-     * @return
-     */
-    private void showSimple() {
-        detailsView.setVisible(false);
-        simpleView.setVisible(true);
-    }
-
-    /**
-     * @return
-     */
-    private void showDetails() {
-        detailsView.setVisible(true);
-        simpleView.setVisible(false);
-    }
-
-    /**
-     * @param e
-     * @return
-     */
-    private void parseInput(TextChangeEvent e) {
-        if(!e.getText().isEmpty()){
-            TimePeriod parsedPeriod = TimePeriodParser.parseString(e.getText());
-            fieldGroup.setItemDataSource(new BeanItem<TimePeriod>(parsedPeriod));
-        }
-    }
-
-    /**
-     *
-     */
-    private void applyDefaultStyles() {
-        if(parseField != null) {
-            parseField.addStyleName(RegistrationStyles.HELPER_FIELD);
-            toLabel.addStyleName("to-label");
-            buttonTextField.addStyleName(ValoTheme.LAYOUT_COMPONENT_GROUP);
-        }
-
-    }
-
-    @Override
-    protected void setInternalValue(TimePeriod newValue) {
-        super.setInternalValue(newValue);
-        fieldGroup.setItemDataSource(new BeanItem<TimePeriod>(newValue));
-
-        updateCacheField();
-    }
-
-    /**
-     * @param newValue
-     */
-    private void updateCacheField() {
-        TimePeriod newValue = fieldGroup.getItemDataSource().getBean();
-        cacheField.setReadOnly(false);
-        cacheField.setValue(timePeriodFormatter.print(newValue));
-        cacheField.setReadOnly(true);
-    }
-
-    @Override
-    public void setStyleName(String style) {
-        super.setStyleName(style);
-        grid.iterator().forEachRemaining(c -> c.setStyleName(style));
-        buttonTextField.iterator().forEachRemaining(c -> c.setStyleName(style));
-        simpleView.iterator().forEachRemaining(c -> c.setStyleName(style));
-        applyDefaultStyles();
-    }
-
-    @Override
-    public void addStyleName(String style) {
-        super.addStyleName(style);
-        grid.iterator().forEachRemaining(c -> c.addStyleName(style));
-        simpleView.iterator().forEachRemaining(c -> {
-            c.addStyleName(style);
-        });
-
-        buttonTextField.iterator().forEachRemaining(c -> c.addStyleName(style));
-    }
-
-    /**
-     * {@inheritDoc}
-     */
-    @Override
-    public Class<? extends TimePeriod> getType() {
-        return TimePeriod.class;
-    }
-
-
-
-}
diff --git a/src/main/java/eu/etaxonomy/cdm/vaadin/component/common/TimePeriodField.java b/src/main/java/eu/etaxonomy/cdm/vaadin/component/common/TimePeriodField.java
new file mode 100644
index 00000000..8a5b7853
--- /dev/null
+++ b/src/main/java/eu/etaxonomy/cdm/vaadin/component/common/TimePeriodField.java
@@ -0,0 +1,272 @@
+/**
+* Copyright (C) 2017 EDIT
+* European Distributed Institute of Taxonomy
+* http://www.e-taxonomy.eu
+*
+* The contents of this file are subject to the Mozilla Public License Version 1.1
+* See LICENSE.TXT at the top of this package for the full license terms.
+*/
+package eu.etaxonomy.cdm.vaadin.component.common;
+
+import java.util.HashSet;
+import java.util.Set;
+
+import com.vaadin.data.fieldgroup.BeanFieldGroup;
+import com.vaadin.data.fieldgroup.FieldGroup.CommitException;
+import com.vaadin.data.util.BeanItem;
+import com.vaadin.event.FieldEvents.TextChangeEvent;
+import com.vaadin.server.FontAwesome;
+import com.vaadin.ui.Alignment;
+import com.vaadin.ui.Button;
+import com.vaadin.ui.Component;
+import com.vaadin.ui.CssLayout;
+import com.vaadin.ui.CustomField;
+import com.vaadin.ui.GridLayout;
+import com.vaadin.ui.Label;
+import com.vaadin.ui.TextField;
+import com.vaadin.ui.themes.ValoTheme;
+
+import eu.etaxonomy.cdm.model.common.TimePeriod;
+import eu.etaxonomy.cdm.strategy.parser.TimePeriodParser;
+import eu.etaxonomy.cdm.vaadin.component.PartialDateField;
+import eu.etaxonomy.cdm.vaadin.component.registration.RegistrationStyles;
+import eu.etaxonomy.cdm.vaadin.util.formatter.DateTimeFormat;
+import eu.etaxonomy.cdm.vaadin.util.formatter.TimePeriodFormatter;
+
+/**
+ * @author a.kohlbecker
+ * @since Apr 6, 2017
+ *
+ */
+public class TimePeriodField extends CustomField<TimePeriod> {
+
+    private static final long serialVersionUID = -7377778547595966252L;
+
+    private static final String PRIMARY_STYLE = "v-time-period-field";
+
+    private BeanFieldGroup<TimePeriod> fieldGroup = new BeanFieldGroup<>(TimePeriod.class);
+
+    TextField parseField = null;
+
+    TextField freeText = null;
+
+    Label toLabel = null;
+
+    GridLayout grid = new GridLayout(3, 4);
+
+    CssLayout detailsView = new CssLayout();
+
+    //TODO implement custom button textfield which does not require a gridLayout
+    GridLayout buttonTextField = new GridLayout(2, 1);
+    GridLayout simpleView = new GridLayout(2, 1);
+
+    TextField cacheField = new TextField();
+
+    Set<Component> styledComponents = new HashSet<>();
+
+    private TimePeriodFormatter timePeriodFormatter = new TimePeriodFormatter(DateTimeFormat.ISO8601_DATE);
+
+    /**
+     *
+     */
+    public TimePeriodField() {
+        super();
+
+    }
+
+    /**
+     * @param string
+     */
+    public TimePeriodField(String string) {
+        this();
+        setCaption(string);
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    @Override
+    protected Component initContent() {
+
+        super.setPrimaryStyleName(PRIMARY_STYLE);
+
+        CssLayout root = new CssLayout();
+
+        initSimpleView();
+        initDetailsView();
+
+        root.addComponent(simpleView);
+        root.addComponent(detailsView);
+
+        applyDefaultStyles();
+
+        showSimple();
+
+        return root;
+    }
+
+    /**
+     *
+     */
+    private void initSimpleView() {
+
+        Button showDetailsButton = new Button(FontAwesome.CALENDAR);
+        showDetailsButton.addClickListener(e -> showDetails());
+        cacheField.setWidth(353, Unit.PIXELS); // FIXME 100% does not work
+
+        simpleView.addStyleName(ValoTheme.LAYOUT_COMPONENT_GROUP);
+        simpleView.setWidth(100, Unit.PERCENTAGE);
+        simpleView.addComponent(showDetailsButton, 0, 0);
+        simpleView.addComponent(cacheField, 1, 0);
+        simpleView.setColumnExpandRatio(1, 0.9f);
+    }
+
+    /**
+     *
+     */
+    private void initDetailsView() {
+
+        parseField = new TextField();
+        // parseField.setWidth(100, Unit.PERCENTAGE);
+        parseField.setInputPrompt("This field will parse the entered time period");
+        parseField.addTextChangeListener(e -> parseInput(e));
+        parseField.setWidth(100, Unit.PERCENTAGE);
+
+        Button closeDetailsButton = new Button(FontAwesome.CLOSE);
+        closeDetailsButton.addClickListener(e -> {
+            try {
+                fieldGroup.commit();
+            } catch (CommitException e1) {
+                // TODO Auto-generated catch block
+                e1.printStackTrace();
+            }
+            updateCacheField();
+            showSimple();
+        });
+
+        buttonTextField.addStyleName(ValoTheme.LAYOUT_COMPONENT_GROUP);
+        buttonTextField.setWidth(100, Unit.PERCENTAGE);
+        buttonTextField.addComponent(closeDetailsButton, 0, 0);
+        buttonTextField.addComponent(parseField, 1, 0);
+        buttonTextField.setColumnExpandRatio(1, 1.0f);
+
+        PartialDateField startDate = new PartialDateField("Start");
+        startDate.setInputPrompt("dd.mm.yyyy");
+        PartialDateField endDate = new PartialDateField("End");
+        endDate.setInputPrompt("dd.mm.yyyy");
+        freeText = new TextField("FreeText");
+        freeText.setWidth(100, Unit.PERCENTAGE);
+
+        fieldGroup.bind(startDate, "start");
+        fieldGroup.bind(endDate, "end");
+        fieldGroup.bind(freeText, "freeText");
+
+        toLabel = new Label("\u2014"); // EM DASH : 0x2014
+
+        int row = 0;
+        grid.addComponent(buttonTextField, 0, row, 2, row);
+        row++;
+        grid.addComponent(startDate, 0, row);
+        grid.addComponent(toLabel, 1, row);
+        grid.setComponentAlignment(toLabel, Alignment.BOTTOM_CENTER);
+        grid.addComponent(endDate, 2, row);
+        row++;
+        grid.addComponent(freeText, 0, row, 2, row);
+
+        // apply the style of the container to all child components. E.g. make all tiny
+        addStyleName((getStyleName()));
+
+        detailsView.setStyleName("margin-wrapper");
+        detailsView.addComponent(grid);
+
+    }
+
+
+    /**
+     * @return
+     */
+    private void showSimple() {
+        detailsView.setVisible(false);
+        simpleView.setVisible(true);
+    }
+
+    /**
+     * @return
+     */
+    private void showDetails() {
+        detailsView.setVisible(true);
+        simpleView.setVisible(false);
+    }
+
+    /**
+     * @param e
+     * @return
+     */
+    private void parseInput(TextChangeEvent e) {
+        if(!e.getText().isEmpty()){
+            TimePeriod parsedPeriod = TimePeriodParser.parseString(e.getText());
+            fieldGroup.setItemDataSource(new BeanItem<TimePeriod>(parsedPeriod));
+        }
+    }
+
+    /**
+     *
+     */
+    private void applyDefaultStyles() {
+        if(parseField != null) {
+            parseField.addStyleName(RegistrationStyles.HELPER_FIELD);
+            toLabel.addStyleName("to-label");
+            buttonTextField.addStyleName(ValoTheme.LAYOUT_COMPONENT_GROUP);
+        }
+
+    }
+
+    @Override
+    protected void setInternalValue(TimePeriod newValue) {
+        super.setInternalValue(newValue);
+        fieldGroup.setItemDataSource(new BeanItem<TimePeriod>(newValue));
+
+        updateCacheField();
+    }
+
+    /**
+     * @param newValue
+     */
+    private void updateCacheField() {
+        TimePeriod newValue = fieldGroup.getItemDataSource().getBean();
+        cacheField.setReadOnly(false);
+        cacheField.setValue(timePeriodFormatter.print(newValue));
+        cacheField.setReadOnly(true);
+    }
+
+    @Override
+    public void setStyleName(String style) {
+        super.setStyleName(style);
+        grid.iterator().forEachRemaining(c -> c.setStyleName(style));
+        buttonTextField.iterator().forEachRemaining(c -> c.setStyleName(style));
+        simpleView.iterator().forEachRemaining(c -> c.setStyleName(style));
+        applyDefaultStyles();
+    }
+
+    @Override
+    public void addStyleName(String style) {
+        super.addStyleName(style);
+        grid.iterator().forEachRemaining(c -> c.addStyleName(style));
+        simpleView.iterator().forEachRemaining(c -> {
+            c.addStyleName(style);
+        });
+
+        buttonTextField.iterator().forEachRemaining(c -> c.addStyleName(style));
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    @Override
+    public Class<? extends TimePeriod> getType() {
+        return TimePeriod.class;
+    }
+
+
+
+}
diff --git a/src/main/java/eu/etaxonomy/cdm/vaadin/ui/RegistrationUI.java b/src/main/java/eu/etaxonomy/cdm/vaadin/ui/RegistrationUI.java
index 251ea28d..9e423d10 100644
--- a/src/main/java/eu/etaxonomy/cdm/vaadin/ui/RegistrationUI.java
+++ b/src/main/java/eu/etaxonomy/cdm/vaadin/ui/RegistrationUI.java
@@ -77,8 +77,9 @@ public class RegistrationUI extends UI {
     }
     //---------------------------------------------
 
-    //private final String INITIAL_VIEW = "workflow/edit/100002";
+    // public static final String INITIAL_VIEW = "workflow/edit/10";
     public static final String INITIAL_VIEW =  DashBoardView.NAME;
+    static boolean debugMode = false;
 
     /*
      * this HACKY solution forces the bean to be instantiated, TODO do it properly
@@ -116,9 +117,6 @@ public class RegistrationUI extends UI {
 
         eventBus.publishEvent(new UIInitializedEvent());
 
-        //navigate to initial view
-        eventBus.publishEvent(new NavigationEvent(INITIAL_VIEW));
-
         String brand = "phycobank";
         //TODO create annotation:
         // @Styles(files={""}, branding="brand")
@@ -128,5 +126,27 @@ public class RegistrationUI extends UI {
         // the 'vaadin://' protocol refers to the VAADIN folder
         Resource registryCssFile = new ExternalResource("vaadin://branding/" + brand + "/css/branding.css");
         Page.getCurrent().getStyles().add(registryCssFile);
+
+        //navigate to initial view
+        String state = pageFragmentAsState();
+
+        if(debugMode && state != null){
+            eventBus.publishEvent(new NavigationEvent(state));
+        } else {
+            eventBus.publishEvent(new NavigationEvent(INITIAL_VIEW));
+        }
+    }
+
+    /**
+     * @return
+     */
+    private String pageFragmentAsState() {
+        Page page = Page.getCurrent();
+        String fragment = page.getUriFragment();
+        String state = null;
+        if(fragment.startsWith("!")){
+            state = fragment.substring(1, fragment.length());
+        }
+        return state;
     }
 }
diff --git a/src/main/java/eu/etaxonomy/cdm/vaadin/view/reference/ReferencePopupEditor.java b/src/main/java/eu/etaxonomy/cdm/vaadin/view/reference/ReferencePopupEditor.java
index 3f16b24c..9ae1b61e 100644
--- a/src/main/java/eu/etaxonomy/cdm/vaadin/view/reference/ReferencePopupEditor.java
+++ b/src/main/java/eu/etaxonomy/cdm/vaadin/view/reference/ReferencePopupEditor.java
@@ -22,7 +22,7 @@ import com.vaadin.ui.TextField;
 
 import eu.etaxonomy.cdm.model.reference.Reference;
 import eu.etaxonomy.cdm.model.reference.ReferenceType;
-import eu.etaxonomy.cdm.vaadin.component.TimePeriodField;
+import eu.etaxonomy.cdm.vaadin.component.common.TimePeriodField;
 import eu.etaxonomy.cdm.vaadin.security.AccessRestrictedView;
 import eu.etaxonomy.vaadin.mvp.AbstractCdmPopupEditor;
 
@@ -86,9 +86,9 @@ public class ReferencePopupEditor extends AbstractCdmPopupEditor<Reference, Refe
         typeSelect.setRows(1);
         addField(typeSelect, "type", 3, row);
         row++;
-        addTextField("Reference cache", "titleCache", 0, row, GRID_COLS-1, row).setWidth(100, Unit.PERCENTAGE);
+        addSwitchableTextField("Reference cache", "titleCache", "protectedTitleCache", 0, row, GRID_COLS-1, row).setWidth(100, Unit.PERCENTAGE);
         row++;
-        addTextField("Abbrev. cache", "abbrevTitleCache", 0, row, GRID_COLS-1, row).setWidth(100, Unit.PERCENTAGE);
+        addSwitchableTextField("Abbrev. cache", "abbrevTitleCache", "protectedAbbrevTitleCache", 0, row, GRID_COLS-1, row).setWidth(100, Unit.PERCENTAGE);
         row++;
         titleField = addTextField("Title", "title", 0, row, GRID_COLS-1, row);
         titleField.setRequired(true);
diff --git a/src/main/java/eu/etaxonomy/vaadin/component/SwitchableTextField.java b/src/main/java/eu/etaxonomy/vaadin/component/SwitchableTextField.java
new file mode 100644
index 00000000..67877862
--- /dev/null
+++ b/src/main/java/eu/etaxonomy/vaadin/component/SwitchableTextField.java
@@ -0,0 +1,165 @@
+/**
+* Copyright (C) 2017 EDIT
+* European Distributed Institute of Taxonomy
+* http://www.e-taxonomy.eu
+*
+* The contents of this file are subject to the Mozilla Public License Version 1.1
+* See LICENSE.TXT at the top of this package for the full license terms.
+*/
+package eu.etaxonomy.vaadin.component;
+
+import org.vaadin.teemu.switchui.Switch;
+
+import com.vaadin.data.fieldgroup.FieldGroup;
+import com.vaadin.ui.Component;
+import com.vaadin.ui.CssLayout;
+import com.vaadin.ui.CustomField;
+import com.vaadin.ui.TextField;
+
+
+/**
+ * @author a.kohlbecker
+ * @since May 11, 2017
+ *
+ */
+public class SwitchableTextField extends CustomField<String> {
+
+    private static final long serialVersionUID = -4760153886584883137L;
+
+    private static final String PRIMARY_STYLE = "v-switchable-textfield";
+
+    CssLayout root = new CssLayout();
+    private TextField textField = new TextField();
+    private SwitchButton unlockSwitch = new SwitchButton();
+
+    /**
+     * @param caption
+     */
+    public SwitchableTextField(String caption) {
+        super();
+        textField.setCaption(caption);
+        unlockSwitch.addValueChangeListener(e -> {
+            textField.setEnabled(unlockSwitch.getValue());
+        });
+        unlockSwitch.setValueSetLister(e -> {
+            textField.setEnabled(unlockSwitch.getValue());
+        });
+    }
+
+    /**
+     * {@inheritDoc}textField
+     */
+    @Override
+    protected Component initContent() {
+        root = new CssLayout();
+        root.addComponent(textField);
+        root.setWidth(getWidth(), getWidthUnits());
+        textField.setWidth(getWidth(), getWidthUnits());
+        root.addComponent(unlockSwitch);
+        setPrimaryStyleName(PRIMARY_STYLE);
+        return root;
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    @Override
+    public Class<? extends String> getType() {
+        return String.class;
+    }
+
+    /**
+     * @return the serialversionuid
+     */
+    public static long getSerialversionuid() {
+        return serialVersionUID;
+    }
+
+    /**
+     * @return the textField
+     */
+    public TextField getTextField() {
+        return textField;
+    }
+
+    /**
+     * @return the unlockSwitch
+     */
+    public Switch getUnlockSwitch() {
+        return unlockSwitch;
+    }
+
+    public void bindTo(FieldGroup fieldGroup, Object textPropertyId, Object switchPropertyId){
+        fieldGroup.bind(textField, textPropertyId);
+        fieldGroup.bind(unlockSwitch, switchPropertyId);
+        textField.setEnabled(unlockSwitch.getValue());
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    @Override
+    public void setWidthUndefined() {
+        super.setWidthUndefined();
+        root.setWidthUndefined();
+        textField.setWidthUndefined();
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    @Override
+    public void setWidth(String width) {
+        super.setWidth(width);
+        root.setWidth(width);
+        textField.setWidth(width);
+    }
+
+    @Override
+    public void setWidth(float width, Unit unit){
+        super.setWidth(width, unit);
+        if(root != null){
+            root.setWidth(width, unit);
+            textField.setWidth(width, unit);
+        }
+    }
+
+    @Override
+    public void setStyleName(String style) {
+        super.setStyleName(style);
+        textField.setStyleName(style);
+        unlockSwitch.setStyleName(style);
+    }
+
+    @Override
+    public void addStyleName(String style) {
+        super.addStyleName(style);
+        textField.addStyleName(style);
+        unlockSwitch.addStyleName(style);
+    }
+
+    private class SwitchButton extends Switch {
+
+        private static final long serialVersionUID = 2557108593729214773L;
+
+        private ValueChangeListener valueSetListener = null;
+
+        /**
+         * {@inheritDoc}
+         */
+        @Override
+        protected void setInternalValue(Boolean newValue) {
+            super.setInternalValue(newValue);
+            if(valueSetListener != null){
+                valueSetListener.valueChange(new ValueChangeEvent(this));
+            }
+        }
+
+        public void setValueSetLister(ValueChangeListener valueSetListener){
+            this.valueSetListener = valueSetListener;
+        }
+
+
+
+    }
+}
diff --git a/src/main/java/eu/etaxonomy/vaadin/mvp/AbstractPopupEditor.java b/src/main/java/eu/etaxonomy/vaadin/mvp/AbstractPopupEditor.java
index c9e87236..7b47e4b5 100644
--- a/src/main/java/eu/etaxonomy/vaadin/mvp/AbstractPopupEditor.java
+++ b/src/main/java/eu/etaxonomy/vaadin/mvp/AbstractPopupEditor.java
@@ -41,6 +41,7 @@ import com.vaadin.ui.TextField;
 import com.vaadin.ui.VerticalLayout;
 import com.vaadin.ui.themes.ValoTheme;
 
+import eu.etaxonomy.vaadin.component.SwitchableTextField;
 import eu.etaxonomy.vaadin.ui.view.DoneWithPopupEvent;
 import eu.etaxonomy.vaadin.ui.view.DoneWithPopupEvent.Reason;
 
@@ -217,6 +218,25 @@ public abstract class AbstractPopupEditor<DTO extends Object, P extends Abstract
         return addField(new TextField(caption), propertyId, column, row);
     }
 
+    protected SwitchableTextField addSwitchableTextField(String caption, String textPropertyId, String switchPropertyId, int column1, int row1,
+            int column2, int row2)
+            throws OverlapsException, OutOfBoundsException {
+
+        SwitchableTextField field = new SwitchableTextField(caption);
+        field.bindTo(fieldGroup, textPropertyId, switchPropertyId);
+        addComponent(field, column1, row1, column2, row2);
+        return field;
+    }
+
+    protected SwitchableTextField addSwitchableTextField(String caption, String textPropertyId, String switchPropertyId, int column, int row)
+            throws OverlapsException, OutOfBoundsException {
+
+        SwitchableTextField field = new SwitchableTextField(caption);
+        field.bindTo(fieldGroup, textPropertyId, switchPropertyId);
+        addComponent(field, column, row);
+        return field;
+    }
+
     protected PopupDateField addDateField(String caption, String propertyId) {
         return addField(new PopupDateField(caption), propertyId);
     }
diff --git a/src/main/java/eu/etaxonomy/vaadin/ui/DevDayWidgetset.gwt.xml b/src/main/java/eu/etaxonomy/vaadin/ui/DevDayWidgetset.gwt.xml
index 2093adca..d6fd5faa 100644
--- a/src/main/java/eu/etaxonomy/vaadin/ui/DevDayWidgetset.gwt.xml
+++ b/src/main/java/eu/etaxonomy/vaadin/ui/DevDayWidgetset.gwt.xml
@@ -14,4 +14,8 @@
     
 
     
+
+    <inherits name="org.vaadin.teemu.switchui.SwitchComponentWidgetset" />
+
+    <inherits name="com.vaadin.addon.onoffswitch.WidgetSet" />
 </module>
diff --git a/src/main/webapp/VAADIN/themes/edit-valo/custom-fields.scss b/src/main/webapp/VAADIN/themes/edit-valo/custom-fields.scss
index bf612fa8..e6c4678a 100644
--- a/src/main/webapp/VAADIN/themes/edit-valo/custom-fields.scss
+++ b/src/main/webapp/VAADIN/themes/edit-valo/custom-fields.scss
@@ -24,5 +24,23 @@ body .edit-valo { // increasing specifity to allow overriding the valo default f
           color: $helper-color;
           background-color: valo-font-color($helper-color);
           border-radius: $v-border-radius;
-      }
+   }
+  
+  // v-switchable-textfield
+  .v-switchable-textfield {
+    height: $v-line-height * 2;
+    .v-caption {
+        display: block;
+    }   
+    .v-textfield {
+        padding-right: $v-unit-size;
+    }
+    .v-switch {
+        z-index: 10;
+        width: $v-unit-size;
+        position: absolute;
+        right: 1px;
+        bottom: 1px;
+    }
+  }
 } 
\ No newline at end of file
