org.chromium.debug.ui/src/org/chromium/debug/ui/source/SourceNameMapperContainerDialogLogic.java
changeset 355 8726e95bcbba
equal deleted inserted replaced
354:0bceeb415e7f 355:8726e95bcbba
       
     1 // Copyright (c) 2010 The Chromium Authors. All rights reserved.
       
     2 // Use of this source code is governed by a BSD-style license that can be
       
     3 // found in the LICENSE file.
       
     4 
       
     5 package org.chromium.debug.ui.source;
       
     6 
       
     7 import static org.chromium.debug.ui.DialogUtils.createErrorOptional;
       
     8 import static org.chromium.debug.ui.DialogUtils.createOptional;
       
     9 
       
    10 import java.util.ArrayList;
       
    11 import java.util.Arrays;
       
    12 import java.util.Collections;
       
    13 import java.util.List;
       
    14 
       
    15 import org.chromium.debug.ui.DialogUtils.ExpressionProcessor;
       
    16 import org.chromium.debug.ui.DialogUtils.Message;
       
    17 import org.chromium.debug.ui.DialogUtils.MessagePriority;
       
    18 import org.chromium.debug.ui.DialogUtils.OkButtonControl;
       
    19 import org.chromium.debug.ui.DialogUtils.Optional;
       
    20 import org.chromium.debug.ui.DialogUtils.Updater;
       
    21 import org.chromium.debug.ui.DialogUtils.ValueConsumer;
       
    22 import org.chromium.debug.ui.DialogUtils.ValueProcessor;
       
    23 import org.chromium.debug.ui.DialogUtils.ValueSource;
       
    24 import org.chromium.debug.ui.source.SourceNameMapperContainerDialog.ConfigureButtonAction;
       
    25 import org.chromium.debug.ui.source.SourceNameMapperContainerDialog.ContainerStatusGroup;
       
    26 import org.chromium.debug.ui.source.SourceNameMapperContainerDialog.Elements;
       
    27 import org.chromium.debug.ui.source.SourceNameMapperContainerDialog.PresetFieldValues;
       
    28 import org.chromium.debug.ui.source.SourceNameMapperContainerDialog.Result;
       
    29 import org.eclipse.debug.core.sourcelookup.ISourceContainer;
       
    30 import org.eclipse.debug.core.sourcelookup.ISourceContainerType;
       
    31 import org.eclipse.debug.core.sourcelookup.ISourceLookupDirector;
       
    32 import org.eclipse.debug.ui.DebugUITools;
       
    33 import org.eclipse.osgi.util.NLS;
       
    34 import org.eclipse.swt.events.ModifyEvent;
       
    35 import org.eclipse.swt.events.ModifyListener;
       
    36 import org.eclipse.swt.events.SelectionAdapter;
       
    37 import org.eclipse.swt.events.SelectionEvent;
       
    38 import org.eclipse.swt.events.SelectionListener;
       
    39 import org.eclipse.swt.graphics.Image;
       
    40 
       
    41 /**
       
    42  * A separated logic of {@link SourceNameMapperContainerDialog}. It describes how data flows
       
    43  * from input elements to the OK button with all necessary asserts. Basically it only uses
       
    44  * {@link SourceNameMapperContainerDialog.Elements} interface from the dialog.
       
    45  */
       
    46 abstract class SourceNameMapperContainerDialogLogic {
       
    47   abstract Result getResult();
       
    48   abstract void updateAll();
       
    49 
       
    50   static SourceNameMapperContainerDialogLogic create(
       
    51       final Elements elements, final ISourceLookupDirector director,
       
    52       final PresetFieldValues initialParams) {
       
    53     final Updater updater = new Updater();
       
    54 
       
    55     final List<ValueSource<String>> warningSources = new ArrayList<ValueSource<String>>(2);
       
    56 
       
    57     // Represents value entered as prefix.
       
    58     final ValueSource<String> prefixEditor = new ValueSource<String>() {
       
    59       public String getValue() {
       
    60         return elements.getPrefixField().getText();
       
    61       }
       
    62       {
       
    63         if (initialParams != null) {
       
    64           elements.getPrefixField().setText(initialParams.getPrefix());
       
    65         }
       
    66         final ValueSource<String> updatableThis = this;
       
    67         ModifyListener listener = new ModifyListener() {
       
    68           public void modifyText(ModifyEvent e) {
       
    69             updater.reportChanged(updatableThis);
       
    70             updater.update();
       
    71           }
       
    72         };
       
    73         elements.getPrefixField().addModifyListener(listener);
       
    74       }
       
    75     };
       
    76 
       
    77     // Represents prefix value after it has been validated.
       
    78     final ValueProcessor<Optional<String>> prefixValue = new ExpressionProcessor<String>(
       
    79         Collections.<ValueSource<? extends Optional<?>>>emptyList()) {
       
    80       @Override
       
    81       protected Optional<String> calculateNormal() {
       
    82         String prefix = prefixEditor.getValue();
       
    83         Optional<String> result;
       
    84         if (prefix == null || prefix.length() == 0) {
       
    85           return createErrorOptional(new Message(
       
    86               Messages.SourceNameMapperContainerDialog_ENTER_PREFIX,
       
    87               MessagePriority.BLOCKING_INFO));
       
    88         } else {
       
    89           return createOptional(prefix);
       
    90         }
       
    91       }
       
    92     };
       
    93     updater.addConsumer(prefixValue, prefixEditor);
       
    94 
       
    95     // Represents possible warning about prefix value having no trailing slash.
       
    96     ValueProcessor<String> noSlashWarning = new ValueProcessor<String>() {
       
    97       public void update(Updater updater) {
       
    98         Optional<String> prefix = prefixValue.getValue();
       
    99         String result;
       
   100         if (prefix.isNormal() && !prefix.getNormal().endsWith("/")) { //$NON-NLS-1$
       
   101           result = Messages.SourceNameMapperContainerDialog_PREFIX_NORMALLY_ENDS;
       
   102         } else {
       
   103           result = null;
       
   104         }
       
   105         setCurrentValue(result);
       
   106         updater.reportChanged(this);
       
   107       }
       
   108     };
       
   109     updater.addConsumer(noSlashWarning, prefixValue);
       
   110     warningSources.add(noSlashWarning);
       
   111 
       
   112     // Represents prefix rule example printer.
       
   113     ValueConsumer prefixExample = new ValueConsumer() {
       
   114       public void update(Updater updater) {
       
   115         Optional<String> prefix = prefixValue.getValue();
       
   116         String line1;
       
   117         String line2;
       
   118         if (prefix.isNormal()) {
       
   119           String sampleFileName = Messages.SourceNameMapperContainerDialog_SAMPLE_FILE_NAME;
       
   120           line1 = NLS.bind(Messages.SourceNameMapperContainerDialog_EXAMPLE_1,
       
   121               prefix.getNormal() + sampleFileName);
       
   122           line2 = NLS.bind(Messages.SourceNameMapperContainerDialog_EXAMPLE_2, sampleFileName);
       
   123         } else {
       
   124           line1 = ""; //$NON-NLS-1$
       
   125           line2 = ""; //$NON-NLS-1$
       
   126         }
       
   127         elements.getPrefixExampleLine1Label().setText(line1);
       
   128         elements.getPrefixExampleLine2Label().setText(line2);
       
   129       }
       
   130     };
       
   131     updater.addConsumer(prefixExample, prefixValue);
       
   132 
       
   133     // Represents container type combo box.
       
   134     final ValueSource<ISourceContainerType> selectedTypeValue =
       
   135         new ValueSource<ISourceContainerType>() {
       
   136       public ISourceContainerType getValue() {
       
   137         return elements.getContainerTypeCombo().getSelected();
       
   138       }
       
   139       {
       
   140         if (initialParams != null) {
       
   141           ISourceContainerType type = initialParams.getContainer().getType();
       
   142           elements.getContainerTypeCombo().setSelected(type);
       
   143         }
       
   144         final ValueSource<ISourceContainerType> updatableThis = this;
       
   145         SelectionListener listener = new SelectionAdapter() {
       
   146           @Override
       
   147           public void widgetSelected(SelectionEvent e) {
       
   148             updater.reportChanged(updatableThis);
       
   149             updater.update();
       
   150           }
       
   151         };
       
   152         elements.getContainerTypeCombo().addSelectionListener(listener);
       
   153       }
       
   154     };
       
   155 
       
   156     // Represents "Configure" button that acts like a container factory.
       
   157     final ValueProcessor<ISourceContainer> containerFactoryButtonValue =
       
   158         new ValueProcessor<ISourceContainer>() {
       
   159       private ConfigureButtonAction preparedAction = null;
       
   160       {
       
   161         if (initialParams != null) {
       
   162           setCurrentValue(initialParams.getContainer());
       
   163         }
       
   164         final ValueSource<ISourceContainer> valueSourceThis = this;
       
   165         elements.getConfigureButton().addSelectionListener(new SelectionAdapter() {
       
   166           @Override
       
   167           public void widgetSelected(SelectionEvent e) {
       
   168             if (preparedAction != null) {
       
   169               ISourceContainer value = preparedAction.run(elements.getShell());
       
   170               if (value != null) {
       
   171                 setCurrentValue(value);
       
   172               }
       
   173               updater.reportChanged(valueSourceThis);
       
   174               updater.update();
       
   175               updateAction();
       
   176             }
       
   177           }
       
   178         });
       
   179       }
       
   180       public void update(Updater updater) {
       
   181         if (getValue() != null && !getValue().getType().equals(selectedTypeValue.getValue())) {
       
   182           setCurrentValue(null);
       
   183           updater.reportChanged(this);
       
   184         }
       
   185         updateAction();
       
   186       }
       
   187       private void updateAction() {
       
   188         preparedAction = SourceNameMapperContainerDialog.prepareConfigureAction(
       
   189             selectedTypeValue.getValue(), getValue(), director);
       
   190         elements.getConfigureButton().setEnabled(preparedAction != null);
       
   191       }
       
   192     };
       
   193     updater.addConsumer(containerFactoryButtonValue, selectedTypeValue);
       
   194 
       
   195     // Represents printer that shows type and name of the created container.
       
   196     ValueConsumer showContainerTypeValue = new ValueConsumer() {
       
   197       public void update(Updater updater) {
       
   198         ISourceContainer container = containerFactoryButtonValue.getValue();
       
   199         String status;
       
   200         Image image;
       
   201         String name;
       
   202         boolean enabled;
       
   203         if (container == null) {
       
   204           status = Messages.SourceNameMapperContainerDialog_NOTHING_CONFIGURED;
       
   205           name = ""; //$NON-NLS-1$
       
   206           image = null;
       
   207           enabled = false;
       
   208         } else {
       
   209           status = Messages.SourceNameMapperContainerDialog_CONFIGURED_CONTAINER;
       
   210           ISourceContainerType type = container.getType();
       
   211           name = container.getName();
       
   212           image = DebugUITools.getSourceContainerImage(type.getId());
       
   213           enabled = true;
       
   214         }
       
   215         ContainerStatusGroup group = elements.getContainerStatusGroup();
       
   216         group.getStatusLabel().setText(status);
       
   217         group.getTypeImageLabel().setImage(image);
       
   218         group.getContainerNameLabel().setText(name);
       
   219         group.setEnabled(enabled);
       
   220         group.layout();
       
   221       }
       
   222     };
       
   223     updater.addConsumer(showContainerTypeValue, containerFactoryButtonValue);
       
   224 
       
   225     // Represents expression that constructs dialog window result.
       
   226     final ValueProcessor<? extends Optional<Result>> resultValue =
       
   227         new ExpressionProcessor<Result>(
       
   228             Arrays.<ValueSource<? extends Optional<?>>>asList(prefixValue) ) {
       
   229           @Override
       
   230           protected Optional<Result> calculateNormal() {
       
   231             final String prefix = prefixValue.getValue().getNormal();
       
   232             final ISourceContainer container = containerFactoryButtonValue.getValue();
       
   233             if (container == null) {
       
   234               return createErrorOptional(
       
   235                   new Message(Messages.SourceNameMapperContainerDialog_CONFIGURE_TARGET_CONTAINER,
       
   236                       MessagePriority.BLOCKING_INFO));
       
   237             }
       
   238             Result result = new Result() {
       
   239               public ISourceContainer getResultContainer() {
       
   240                 return container;
       
   241               }
       
   242               public String getResultPrefix() {
       
   243                 return prefix;
       
   244               }
       
   245             };
       
   246             return createOptional(result);
       
   247           }
       
   248     };
       
   249     updater.addConsumer(resultValue, prefixValue, containerFactoryButtonValue);
       
   250 
       
   251     // Represents controller that updates state of OK button and error messages.
       
   252     OkButtonControl okButtonControl = new OkButtonControl(resultValue, warningSources, elements);
       
   253     updater.addConsumer(okButtonControl, okButtonControl.getDependencies());
       
   254 
       
   255     return new SourceNameMapperContainerDialogLogic() {
       
   256       @Override
       
   257       Result getResult() {
       
   258         Optional<Result> optional = resultValue.getValue();
       
   259         if (optional.isNormal()) {
       
   260           return optional.getNormal();
       
   261         } else {
       
   262           // Normally should not be reachable, because UI should have disabled OK button.
       
   263           return null;
       
   264         }
       
   265       }
       
   266       @Override
       
   267       void updateAll() {
       
   268         updater.updateAll();
       
   269       }
       
   270     };
       
   271   }
       
   272 }