/*
   * (non-Javadoc)
   *
   * @see org.eclipse.jface.bindings.keys.AbstractKeyFormatter#sortModifierKeys(int)
   */
  protected int[] sortModifierKeys(final int modifierKeys) {
    final IKeyLookup lookup = KeyLookupFactory.getDefault();
    final int[] sortedKeys = new int[4];
    int index = 0;

    if (Util.isWindows()) {
      if ((modifierKeys & lookup.getCtrl()) != 0) {
        sortedKeys[index++] = lookup.getCtrl();
      }
      if ((modifierKeys & lookup.getAlt()) != 0) {
        sortedKeys[index++] = lookup.getAlt();
      }
      if ((modifierKeys & lookup.getShift()) != 0) {
        sortedKeys[index++] = lookup.getShift();
      }

    } else if (Util.isGtk() || Util.isMotif()) {
      if ((modifierKeys & lookup.getShift()) != 0) {
        sortedKeys[index++] = lookup.getShift();
      }
      if ((modifierKeys & lookup.getCtrl()) != 0) {
        sortedKeys[index++] = lookup.getCtrl();
      }
      if ((modifierKeys & lookup.getAlt()) != 0) {
        sortedKeys[index++] = lookup.getAlt();
      }

    } else if (Util.isMac()) {
      if ((modifierKeys & lookup.getShift()) != 0) {
        sortedKeys[index++] = lookup.getShift();
      }
      if ((modifierKeys & lookup.getCtrl()) != 0) {
        sortedKeys[index++] = lookup.getCtrl();
      }
      if ((modifierKeys & lookup.getAlt()) != 0) {
        sortedKeys[index++] = lookup.getAlt();
      }
      if ((modifierKeys & lookup.getCommand()) != 0) {
        sortedKeys[index++] = lookup.getCommand();
      }
    }

    return sortedKeys;
  }
  /**
   * Returns the change that will be executed when the proposal is applied. This method calls {@link
   * #createChange()} to compute the change.
   *
   * @return the change for this proposal, can be <code>null</code> in rare cases if creation of the
   *     change failed
   * @throws CoreException when the change could not be created
   */
  public final Change getChange() throws CoreException {
    if (Util.isGtk()) {
      // workaround for https://bugs.eclipse.org/bugs/show_bug.cgi?id=293995 :
      // [Widgets] Deadlock while UI thread displaying/computing a change proposal and non-UI thread
      // creating image

      // Solution is to create the change outside a 'synchronized' block.
      // Synchronization is achieved by polling fChange, using "fChange == COMPUTING_CHANGE" as
      // barrier.
      // Timeout of 10s for safety reasons (should not be reached).
      long end = System.currentTimeMillis() + 10000;
      do {
        boolean computing;
        synchronized (this) {
          computing = fChange == COMPUTING_CHANGE;
        }
        if (computing) {
          try {
            Display display = Display.getCurrent();
            if (display != null) {
              while (!display.isDisposed() && display.readAndDispatch()) {
                // empty the display loop
              }
              display.sleep();
            } else {
              Thread.sleep(100);
            }
          } catch (InterruptedException e) {
            // continue
          }
        } else {
          synchronized (this) {
            if (fChange == COMPUTING_CHANGE) {
              continue;
            } else if (fChange != null) {
              return fChange;
            } else {
              fChange = COMPUTING_CHANGE;
            }
          }
          Change change = createChange();
          synchronized (this) {
            fChange = change;
          }
          return change;
        }
      } while (System.currentTimeMillis() < end);

      synchronized (this) {
        if (fChange == COMPUTING_CHANGE) {
          return null; // failed
        }
      }

    } else {
      synchronized (this) {
        if (fChange == null) {
          fChange = createChange();
        }
      }
    }
    return fChange;
  }