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

com.google.gwtexpui.globalkey.client.KeyHelpPopup Maven / Gradle / Ivy

There is a newer version: 2.16.28
Show newest version
// Copyright (C) 2009 The Android Open Source Project
//
// 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.gwtexpui.globalkey.client;

import com.google.gwt.event.dom.client.ClickEvent;
import com.google.gwt.event.dom.client.ClickHandler;
import com.google.gwt.event.dom.client.KeyCodes;
import com.google.gwt.event.dom.client.KeyDownEvent;
import com.google.gwt.event.dom.client.KeyDownHandler;
import com.google.gwt.event.dom.client.KeyPressEvent;
import com.google.gwt.event.dom.client.KeyPressHandler;
import com.google.gwt.user.client.DOM;
import com.google.gwt.user.client.ui.Anchor;
import com.google.gwt.user.client.ui.FlowPanel;
import com.google.gwt.user.client.ui.FocusPanel;
import com.google.gwt.user.client.ui.Grid;
import com.google.gwt.user.client.ui.HTMLTable.CellFormatter;
import com.google.gwt.user.client.ui.HasHorizontalAlignment;
import com.google.gwt.user.client.ui.PopupPanel;
import com.google.gwtexpui.safehtml.client.SafeHtml;
import com.google.gwtexpui.safehtml.client.SafeHtmlBuilder;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.Comparator;
import java.util.HashMap;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;

public class KeyHelpPopup extends PopupPanel implements KeyPressHandler, KeyDownHandler {
  private final FocusPanel focus;

  public KeyHelpPopup() {
    super(true /* autohide */, true /* modal */);
    setStyleName(KeyResources.I.css().helpPopup());

    final Anchor closer = new Anchor(KeyConstants.I.closeButton());
    closer.addClickHandler(
        new ClickHandler() {
          @Override
          public void onClick(final ClickEvent event) {
            hide();
          }
        });

    final Grid header = new Grid(1, 3);
    header.setStyleName(KeyResources.I.css().helpHeader());
    header.setText(0, 0, KeyConstants.I.keyboardShortcuts());
    header.setWidget(0, 2, closer);

    final CellFormatter fmt = header.getCellFormatter();
    fmt.addStyleName(0, 1, KeyResources.I.css().helpHeaderGlue());
    fmt.setHorizontalAlignment(0, 2, HasHorizontalAlignment.ALIGN_RIGHT);

    final Grid lists = new Grid(0, 7);
    lists.setStyleName(KeyResources.I.css().helpTable());
    populate(lists);
    lists.getCellFormatter().addStyleName(0, 3, KeyResources.I.css().helpTableGlue());

    final FlowPanel body = new FlowPanel();
    body.add(header);
    body.getElement().appendChild(DOM.createElement("hr"));
    body.add(lists);

    focus = new FocusPanel(body);
    focus.getElement().getStyle().setProperty("outline", "0px");
    focus.getElement().setAttribute("hideFocus", "true");
    focus.addKeyPressHandler(this);
    focus.addKeyDownHandler(this);
    add(focus);
  }

  @Override
  public void setVisible(final boolean show) {
    super.setVisible(show);
    if (show) {
      focus.setFocus(true);
    }
  }

  @Override
  public void onKeyPress(final KeyPressEvent event) {
    if (KeyCommandSet.toMask(event) == ShowHelpCommand.INSTANCE.keyMask) {
      // Block the '?' key from triggering us to show right after
      // we just hide ourselves.
      //
      event.stopPropagation();
      event.preventDefault();
    }
    hide();
  }

  @Override
  public void onKeyDown(final KeyDownEvent event) {
    if (event.getNativeKeyCode() == KeyCodes.KEY_ESCAPE) {
      hide();
    }
  }

  private void populate(final Grid lists) {
    int[] end = new int[5];
    int column = 0;
    for (final KeyCommandSet set : combinedSetsByName()) {
      int row = end[column];
      row = formatGroup(lists, row, column, set);
      end[column] = row;
      if (column == 0) {
        column = 4;
      } else {
        column = 0;
      }
    }
  }

  /**
   * @return an ordered collection of KeyCommandSet, combining sets which share the same name, so
   *     that each set name appears at most once.
   */
  private static Collection combinedSetsByName() {
    LinkedHashMap byName = new LinkedHashMap<>();
    for (final KeyCommandSet set : GlobalKey.active.all.getSets()) {
      KeyCommandSet v = byName.get(set.getName());
      if (v == null) {
        v = new KeyCommandSet(set.getName());
        byName.put(v.getName(), v);
      }
      v.add(set);
    }
    return byName.values();
  }

  private int formatGroup(final Grid lists, int row, final int col, final KeyCommandSet set) {
    if (set.isEmpty()) {
      return row;
    }

    if (lists.getRowCount() < row + 1) {
      lists.resizeRows(row + 1);
    }
    lists.setText(row, col + 2, set.getName());
    lists.getCellFormatter().addStyleName(row, col + 2, KeyResources.I.css().helpGroup());
    row++;

    return formatKeys(lists, row, col, set, null);
  }

  private int formatKeys(
      final Grid lists, int row, final int col, final KeyCommandSet set, final SafeHtml prefix) {
    final CellFormatter fmt = lists.getCellFormatter();
    final List keys = sort(set);
    if (lists.getRowCount() < row + keys.size()) {
      lists.resizeRows(row + keys.size());
    }

    Map rows = new HashMap<>();
    FORMAT_KEYS:
    for (int i = 0; i < keys.size(); i++) {
      final KeyCommand k = keys.get(i);
      if (rows.containsKey(k)) {
        continue;
      }

      if (k instanceof CompoundKeyCommand) {
        final SafeHtmlBuilder b = new SafeHtmlBuilder();
        b.append(k.describeKeyStroke());
        row = formatKeys(lists, row, col, ((CompoundKeyCommand) k).getSet(), b);
        continue;
      }

      for (int prior = 0; prior < i; prior++) {
        if (KeyCommand.same(keys.get(prior), k)) {
          final int r = rows.get(keys.get(prior));
          final SafeHtmlBuilder b = new SafeHtmlBuilder();
          b.append(SafeHtml.get(lists, r, col + 0));
          b.append(" ");
          b.append(KeyConstants.I.orOtherKey());
          b.append(" ");
          if (prefix != null) {
            b.append(prefix);
            b.append(" ");
            b.append(KeyConstants.I.thenOtherKey());
            b.append(" ");
          }
          b.append(k.describeKeyStroke());
          SafeHtml.set(lists, r, col + 0, b);
          rows.put(k, r);
          continue FORMAT_KEYS;
        }
      }

      SafeHtmlBuilder b = new SafeHtmlBuilder();
      String t = k.getHelpText();
      if (prefix != null) {
        b.append(prefix);
        b.append(" ");
        b.append(KeyConstants.I.thenOtherKey());
        b.append(" ");
      }
      b.append(k.describeKeyStroke());
      if (k.sibling != null) {
        b.append(" / ").append(k.sibling.describeKeyStroke());
        t += " / " + k.sibling.getHelpText();
        rows.put(k.sibling, row);
      }
      SafeHtml.set(lists, row, col + 0, b);
      lists.setText(row, col + 1, ":");
      lists.setText(row, col + 2, t);
      rows.put(k, row);

      fmt.addStyleName(row, col + 0, KeyResources.I.css().helpKeyStroke());
      fmt.addStyleName(row, col + 1, KeyResources.I.css().helpSeparator());
      row++;
    }

    return row;
  }

  private List sort(final KeyCommandSet set) {
    final List keys = new ArrayList<>(set.getKeys());
    Collections.sort(
        keys,
        new Comparator() {
          @Override
          public int compare(KeyCommand arg0, KeyCommand arg1) {
            return arg0.getHelpText().compareTo(arg1.getHelpText());
          }
        });
    return keys;
  }
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy