Package com.google.collide.client.workspace

Source Code of com.google.collide.client.workspace.RunButtonTargetPopup$Css

// Copyright 2012 Google Inc. All Rights Reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

package com.google.collide.client.workspace;

import com.google.collide.client.AppContext;
import com.google.collide.client.common.BaseResources;
import com.google.collide.client.search.FileNameSearch;
import com.google.collide.client.ui.dropdown.AutocompleteController;
import com.google.collide.client.ui.dropdown.DropdownController;
import com.google.collide.client.ui.dropdown.DropdownWidgets;
import com.google.collide.client.ui.dropdown.AutocompleteController.AutocompleteHandler;
import com.google.collide.client.ui.dropdown.DropdownController.BaseListener;
import com.google.collide.client.ui.dropdown.DropdownController.DropdownPositionerBuilder;
import com.google.collide.client.ui.dropdown.DropdownWidgets.DropdownInput;
import com.google.collide.client.ui.list.SimpleList.ListItemRenderer;
import com.google.collide.client.ui.menu.AutoHideComponent;
import com.google.collide.client.ui.menu.AutoHideView;
import com.google.collide.client.ui.menu.PositionController;
import com.google.collide.client.ui.menu.AutoHideComponent.AutoHideModel;
import com.google.collide.client.ui.menu.PositionController.HorizontalAlign;
import com.google.collide.client.ui.menu.PositionController.Positioner;
import com.google.collide.client.ui.menu.PositionController.VerticalAlign;
import com.google.collide.client.util.ClientStringUtils;
import com.google.collide.client.util.Elements;
import com.google.collide.client.util.PathUtil;
import com.google.collide.dto.RunTarget;
import com.google.collide.dto.RunTarget.RunMode;
import com.google.collide.dto.client.DtoClientImpls.RunTargetImpl;
import com.google.collide.json.shared.JsonArray;
import com.google.collide.shared.util.RegExpUtils;
import com.google.collide.shared.util.StringUtils;
import com.google.gwt.core.client.GWT;
import com.google.gwt.dom.client.DivElement;
import com.google.gwt.dom.client.Element;
import com.google.gwt.dom.client.InputElement;
import com.google.gwt.dom.client.LabelElement;
import com.google.gwt.dom.client.SpanElement;
import com.google.gwt.regexp.shared.RegExp;
import com.google.gwt.resources.client.CssResource;
import com.google.gwt.resources.client.ImageResource;
import com.google.gwt.uibinder.client.UiBinder;
import com.google.gwt.uibinder.client.UiField;
import com.google.gwt.uibinder.client.UiTemplate;
import com.google.gwt.user.client.ui.HTMLPanel;

import elemental.dom.Node;
import elemental.events.Event;
import elemental.events.EventListener;
import elemental.events.KeyboardEvent;

/**
* A popup for user selection of the run target.
*/
public class RunButtonTargetPopup
    extends AutoHideComponent<RunButtonTargetPopup.View, AutoHideModel> {

  public static RunButtonTargetPopup create(AppContext context, Element anchorElement,
      Element triggerElement, FileNameSearch searchIndex) {
    View view = new View(context.getResources());
    return new RunButtonTargetPopup(view, anchorElement, triggerElement, searchIndex);
  }

  /**
   * An enum which handles the different types of files that can be parsed out of a user's file
   * input. Each enum value also provides the appropriate labels and formatter for the user provided
   * values.
   */
  public enum RunTargetType {
    /**
     * Represents any other value typed into the dropdown. This file will be executed on the
     * resource serving servlet.
     */
    FILE("Query", "?query string (optional)", new InputFormatter() {
      @Override
      public String formatUserInput(String file, String userValue) {
        if (userValue.isEmpty()) {
          return StringUtils.ensureStartsWith(file, "/");
        } else {
          return StringUtils.ensureStartsWith(file, "/")
              + StringUtils.ensureStartsWith(userValue, "?");
        }
      }
    });

    /**
     * An object which formats some output based on the file name and query value provided by the
     * user.
     */
    public interface InputFormatter {
      String formatUserInput(String file, String userValue);
    }

    /**
     * An object which can be used for run targets which do not need to provide a formatted output.
     */
    public static final class NoInputFormatter implements InputFormatter {
      @Override
      public String formatUserInput(String file, String userValue) {
        return "";
      }
    }

    private final String label;
    private final String placeHolder;
    private final InputFormatter inputFormatter;

    RunTargetType(String label, String placeHolder, InputFormatter inputFormatter) {
      this.label = label;
      this.placeHolder = placeHolder;
      this.inputFormatter = inputFormatter;
    }

    /**
     * Parses the user's input and determines the type of run target.
     */
    public static RunTargetType parseTargetType(String fileInput) {
      return RunTargetType.FILE;
    }
  }

  public interface Css extends CssResource {
    String container();

    String radio();

    String stackedContainer();

    String smallPreviewText();

    String alwaysRunRow();

    String alwaysRunInput();

    String alwaysRunLabel();

    String alwaysRunUrl();

    String appUrlLabel();

    String autocompleteFolder();

    String listItem();

    /* Sets the dropdown opacity to 1 while the menu is visible */
    String stayActive();
  }

  public interface Resources extends BaseResources.Resources, DropdownWidgets.Resources {
    @Source("RunButtonTargetPopup.css")
    Css runButtonTargetPopupCss();

    @Source("appengine-small.png")
    ImageResource appengineSmall();
  }

  public interface ViewEvents {
    void onAlwaysRunInputChanged();

    void onPathInputChanged();
  }

  public class ViewEventsImpl implements ViewEvents {
    @Override
    public void onAlwaysRunInputChanged() {
      selectRadio(RunMode.ALWAYS_RUN);
      getView().setDisplayForRunningApp();
    }

    @Override
    public void onPathInputChanged() {
      selectRadio(RunMode.ALWAYS_RUN);
      getView().setDisplayForRunningApp();
    }
  }

  private static final int MAX_AUTOCOMPLETE_RESULTS = 4;

  private final FileNameSearch searchIndex;
  private final PositionController positionController;
  private AutocompleteController<PathUtil> autocompleteController;

  private RunButtonTargetPopup(
      View view, Element anchorElement, Element triggerElement, FileNameSearch searchIndex) {
    super(view, new AutoHideModel());
    view.setDelegate(new ViewEventsImpl());

    this.searchIndex = searchIndex;
    setupAutocomplete();

    // Don't eat outside clicks and only hide when the user clicks away
    addPartnerClickTargets(
        Elements.asJsElement(triggerElement), autocompleteController.getDropdown().getElement());
    setCaptureOutsideClickOnClose(false);
    setDelay(-1);

    // Position Controller
    positionController =
        new PositionController(new PositionController.PositionerBuilder().setVerticalAlign(
            VerticalAlign.BOTTOM).setHorizontalAlign(HorizontalAlign.LEFT)
            .buildAnchorPositioner(Elements.asJsElement(anchorElement)), getView().getElement());
  }

  private void setupAutocomplete() {
    AutocompleteHandler<PathUtil> handler = new AutocompleteHandler<PathUtil>() {
      @Override
      public JsonArray<PathUtil> doCompleteQuery(String query) {
        PathUtil searchPath = PathUtil.WORKSPACE_ROOT;
        // the PathUtil.createExcluding wasn't used here since it doesn't make
        // /test2/ into a path containing /test2 but instead makes it /
        if (query.lastIndexOf(PathUtil.SEP) != -1) {
          searchPath = new PathUtil(query.substring(0, query.lastIndexOf(PathUtil.SEP)));
          query = query.substring(query.lastIndexOf(PathUtil.SEP) + 1);
        }

        // Only the non folder part (if it exists) is supported for wildcards
        RegExp reQuery = RegExpUtils.createRegExpForWildcardPattern(
            query, ClientStringUtils.containsUppercase(query) ? "" : "i");
        return searchIndex.getMatchesRelativeToPath(searchPath, reQuery, MAX_AUTOCOMPLETE_RESULTS);
      }

      @Override
      public void onItemSelected(PathUtil item) {
        getView().runAlwaysDropdown.getInput().setValue(item.getPathString());
        getView().setDisplayForRunningApp();
      }
    };

    BaseListener<PathUtil> clickListener = new BaseListener<PathUtil>() {
      @Override
      public void onItemClicked(PathUtil item) {
        getView().runAlwaysDropdown.getInput().setValue(item.getPathString());
        getView().setDisplayForRunningApp();
      }
    };

    ListItemRenderer<PathUtil> itemRenderer = new ListItemRenderer<PathUtil>() {
      @Override
      public void render(elemental.html.Element listItemBase, PathUtil itemData) {
        elemental.html.SpanElement fileNameElement = Elements.createSpanElement();
        elemental.html.SpanElement folderNameElement = Elements.createSpanElement(
            getView().res.runButtonTargetPopupCss().autocompleteFolder());

        listItemBase.appendChild(fileNameElement);
        listItemBase.appendChild(folderNameElement);

        int size = itemData.getPathComponentsCount();
        if (size == 1) {
          fileNameElement.setTextContent(itemData.getPathComponent(0));
          folderNameElement.setTextContent("");
        } else {
          fileNameElement.setTextContent(itemData.getPathComponent(size - 1));
          folderNameElement.setTextContent(" - " + itemData.getPathComponent(size - 2));
        }
      }
    };

    Positioner positioner = new DropdownPositionerBuilder().buildAnchorPositioner(
        getView().runAlwaysDropdown.getInput());
    DropdownController<PathUtil> autocompleteDropdown = new DropdownController.Builder<PathUtil>(
        positioner, null, getView().res, clickListener, itemRenderer).setInputTargetElement(
        getView().runAlwaysDropdown.getInput())
        .setShouldAutoFocusOnOpen(false).setKeyboardSelectionEnabled(true).build();

    autocompleteController = AutocompleteController.create(
        getView().runAlwaysDropdown.getInput(), autocompleteDropdown, handler);
  }

  public void updateCurrentFile(String filePath) {
    getView().runPreviewCurrentFile.setInnerText(
        StringUtils.ensureNotEmpty(filePath, "Select a file"));
  }

  private void selectRadio(RunMode mode) {
    elemental.html.Element preview = Elements.asJsElement(getView().runPreviewRadio);
    elemental.html.Element always = Elements.asJsElement(getView().runAlwaysRadio);

    preview.setChecked(mode == RunMode.PREVIEW_CURRENT_FILE);
    always.setChecked(mode == RunMode.ALWAYS_RUN);
  }

  public void setRunTarget(RunTarget runTarget) {
    selectRadio(runTarget.getRunMode());
    getView().runAlwaysDropdown.getInput().setValue(StringUtils.nullToEmpty(
        runTarget.getAlwaysRunFilename()));
    getView().userExtraInput.setValue(StringUtils.nullToEmpty(runTarget.getAlwaysRunUrlOrQuery()));
  }

  public RunTarget getRunTarget() {
    RunTargetImpl runTarget = RunTargetImpl.make();

    boolean isPreviewMode = Elements.asJsElement(getView().runPreviewRadio).isChecked();
    runTarget.setRunMode(isPreviewMode ? RunMode.PREVIEW_CURRENT_FILE : RunMode.ALWAYS_RUN);

    runTarget.setAlwaysRunFilename(getView().runAlwaysDropdown.getInput().getValue());
    runTarget.setAlwaysRunUrlOrQuery(getView().userExtraInput.getValue());

    return runTarget;
  }

  @Override
  public void show() {
    // Position Ourselves
    positionController.updateElementPosition();

    // Update UI before we show
    getView().setDisplayForRunningApp();

    super.show();
  }

  public static class View extends AutoHideView<ViewEvents> {
    @UiTemplate("RunButtonTargetPopup.ui.xml")
    interface RunButtonDropdownUiBinder extends UiBinder<Element, View> {
    }

    private static RunButtonDropdownUiBinder uiBinder = GWT.create(RunButtonDropdownUiBinder.class);

    @UiField(provided = true)
    final Resources res;

    // Preview Current File Stuff
    @UiField
    InputElement runPreviewRadio;

    @UiField
    LabelElement runPreviewLabel;

    @UiField
    SpanElement runPreviewCurrentFile;

    // Run always stuff
    @UiField
    DivElement runAlwaysRow;

    @UiField
    InputElement runAlwaysRadio;

    @UiField
    LabelElement runAlwaysLabel;

    final DropdownInput runAlwaysDropdown;

    // Query and URL Box
    @UiField
    LabelElement userExtraLabel;

    @UiField
    InputElement userExtraInput;

    // Full Query URL
    @UiField
    DivElement runHintText;

    public View(Resources resources) {
      this.res = resources;

      Element element = uiBinder.createAndBindUi(this);
      setElement(Elements.asJsElement(element));
      Elements.getBody().appendChild((Node) element);

      // Workaround for inability to set both id and ui:field in a UiBinder XML
      runAlwaysRadio.setId(HTMLPanel.createUniqueId());
      runAlwaysLabel.setHtmlFor(runAlwaysRadio.getId());
      userExtraLabel.setHtmlFor(runAlwaysRadio.getId());

      runPreviewRadio.setId(HTMLPanel.createUniqueId());
      runPreviewLabel.setHtmlFor(runPreviewRadio.getId());

      // Create the dropdown
      runAlwaysDropdown = new DropdownInput(resources);
      runAlwaysDropdown.getInput()
          .addClassName(resources.runButtonTargetPopupCss().alwaysRunInput());
      runAlwaysDropdown.getInput().setAttribute("placeholder", "Enter filename");
      Elements.asJsElement(runAlwaysRow).appendChild(runAlwaysDropdown.getContainer());

      setDisplayForRunningApp(RunTargetType.FILE);
      attachHandlers();
    }

    public void attachHandlers() {
      runAlwaysDropdown.getInput().addEventListener(Event.INPUT, new EventListener() {
        @Override
        public void handleEvent(Event evt) {
          if (getDelegate() != null) {
            getDelegate().onAlwaysRunInputChanged();
          }
        }
      }, false);

      Elements.asJsElement(userExtraInput).addEventListener(Event.INPUT, new EventListener() {
        @Override
        public void handleEvent(Event evt) {
          if (getDelegate() != null) {
            getDelegate().onPathInputChanged();
          }
        }
      }, false);

      EventListener onEnterListener = new EventListener() {
        @Override
        public void handleEvent(Event evt) {
          if (getDelegate() != null) {
            KeyboardEvent keyEvent = (KeyboardEvent) evt;
            if (keyEvent.getKeyCode() == KeyboardEvent.KeyCode.ENTER) {
              getDelegate().onPathInputChanged();
              evt.stopPropagation();
              hide();
            }
          }
        }
      };

      runAlwaysDropdown.getInput().addEventListener(Event.KEYUP, onEnterListener, false);
      Elements.asJsElement(userExtraInput).addEventListener(Event.KEYUP, onEnterListener, false);
    }

    /**
     * Sets up the view based on the user's current file input value.
     */
    public void setDisplayForRunningApp() {
      RunTargetType type = RunTargetType.parseTargetType(runAlwaysDropdown.getInput().getValue());
      setDisplayForRunningApp(type);
    }

    /**
     * Sets up the view for the supplied app type.
     */
    public void setDisplayForRunningApp(RunTargetType appType) {
      userExtraInput.setAttribute("placeholder", appType.placeHolder);
      userExtraLabel.setInnerText(appType.label);

      String fileName = runAlwaysDropdown.getInput().getValue();
      String queryText = userExtraInput.getValue();
      if (fileName.isEmpty()) {
        runHintText.setInnerText("Type a filename");
      } else {
        runHintText.setInnerText(appType.inputFormatter.formatUserInput(fileName, queryText));
      }
    }
  }
}
TOP

Related Classes of com.google.collide.client.workspace.RunButtonTargetPopup$Css

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.