Package com.mucommander.ui.dialog.customization

Source Code of com.mucommander.ui.dialog.customization.CommandBarDialog$CommandBarButtonListCellRenderer

/*
* This file is part of muCommander, http://www.mucommander.com
* Copyright (C) 2002-2012 Maxence Bernard
*
* muCommander is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 3 of the License, or
* (at your option) any later version.
*
* muCommander is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program.  If not, see <http://www.gnu.org/licenses/>.
*/

package com.mucommander.ui.dialog.customization;

import com.mucommander.commons.collections.AlteredVector;
import com.mucommander.text.Translator;
import com.mucommander.ui.action.ActionManager;
import com.mucommander.ui.action.ActionProperties;
import com.mucommander.ui.action.impl.CustomizeCommandBarAction;
import com.mucommander.ui.layout.YBoxPanel;
import com.mucommander.ui.list.DynamicHorizontalWrapList;
import com.mucommander.ui.list.DynamicList;
import com.mucommander.ui.main.MainFrame;
import com.mucommander.ui.main.commandbar.CommandBarAttributes;
import com.mucommander.ui.main.commandbar.CommandBarButtonForDisplay;
import com.mucommander.ui.main.commandbar.CommandBarIO;
import com.mucommander.ui.text.RecordingKeyStrokeTextField;

import javax.swing.*;
import javax.swing.Box.Filler;
import java.awt.*;
import java.awt.datatransfer.DataFlavor;
import java.awt.datatransfer.Transferable;
import java.awt.datatransfer.UnsupportedFlavorException;
import java.awt.event.KeyEvent;
import java.io.IOException;
import java.util.*;
import java.util.List;

/**
* Dialog used to customize the command-bar.
*
* @author Arik Hadas
*/
public class CommandBarDialog extends CustomizeDialog {
 
  /** List that contains all available buttons, i.e buttons that are not used by the command bar */
  private DynamicHorizontalWrapList<JButton> commandBarAvailableButtonsList;
  /** List that contains the command-bar regular buttons (i.e, not alternative buttons) */
  private DynamicList<JButton>  commandBarButtonsList;
  /** List that contains the command-bar alternative buttons */
  private DynamicList<JButton> commandBarAlternateButtonsList;
 
  /** Vector that contains the buttons in the available buttons list */
  private AlteredVector<JButton> commandBarAvailableButtons;
  /** Vector that contains the buttons in the command-bar regular buttons list */
  private AlteredVector<JButton> commandBarButtons;
  /** Vector that contains the buttons in the command-bar alternate buttons list */
  private AlteredVector<JButton> commandBarAlternateButtons;
  /** Field which allows the user to enter new KeyStroke modifier for command-bar */
  private RecordingKeyStrokeTextField modifierField;
 
  /** Modifier text field length  */
  private static final int MODIFIER_FIELD_MAX_LENGTH = 6;
 
  /** The default color of button's border */
  private static final Color JBUTTON_BACKGROUND_COLOR = UIManager.getColor("button.background");
 
  /** Comparator for buttons according to their text */
  private static final Comparator<JButton> BUTTONS_COMPARATOR = new Comparator<JButton>() {
    public int compare(JButton b1, JButton b2) {
      if (b1.getText() == null)
        return 1;
      if (b2.getText() == null)
        return -1;
      return b1.getText().compareTo(b2.getText());
    }
  };
 
  /**
   * Constructor
   */
    public CommandBarDialog(MainFrame mainFrame) {
    super(mainFrame, ActionProperties.getActionLabel(CustomizeCommandBarAction.Descriptor.ACTION_ID));
  }
 
    @Override
    protected void componentChanged() {
      setCommitButtonsEnabled(getNumberOfButtons() > 0 && (areActionsChanged() || areAlternativeActionsChanged() || isModifierChanged()));       
    }
   
    @Override
    protected void commit() {
    int nbNewActions = getNumberOfButtons();
    String[] newActionIds = new String[nbNewActions];
    for (int i=0; i<nbNewActions; ++i) {
      newActionIds[i] = ((CommandBarButtonForDisplay) commandBarButtons.get(i)).getActionId();
    }
   
    int nbNewAlternativeActions = commandBarAlternateButtons.size();
    String[] newAlternativeActionIds = new String[nbNewAlternativeActions];
    for (int i=0; i<nbNewAlternativeActions; ++i) {
      Object button = commandBarAlternateButtons.get(i);
      newAlternativeActionIds[i] = (button != null) ?
                    ((CommandBarButtonForDisplay) button).getActionId() : null;
    }
   
    CommandBarAttributes.setAttributes(newActionIds, newAlternativeActionIds, modifierField.getKeyStroke());
    CommandBarIO.setModified();
  }

  @Override
    protected JPanel createCustomizationPanel() {
    JPanel panel = new JPanel(new BorderLayout());
   
    commandBarAvailableButtons   = new AlteredVector<JButton>();
    commandBarButtons            = new AlteredVector<JButton>();
    commandBarAlternateButtons   = new AlteredVector<JButton>();
   
    // a Set that contains all actions that are used by the command-bar (as regular or alternate buttons).
    Set<String> usedActions = new HashSet<String>();
    usedActions.addAll(initCommandBarActionsList());
    usedActions.addAll(initCommandBarAlternateActionsList());
    initActionsPoolList(usedActions);
   
    panel.add(createAvailableButtonsPanel(), BorderLayout.CENTER);
    panel.add(createCommandBarPanel(), BorderLayout.SOUTH);
   
    return panel;
  }
   
    private boolean areActionsChanged() {
      // Fetch command-bar action ids
      String[] commandBarActionIds = CommandBarAttributes.getActions();
      int nbActions = commandBarActionIds.length;
     
      if (nbActions != getNumberOfButtons())
        return true;
     
      for (int i=0; i<nbActions; ++i) {
        CommandBarButtonForDisplay buttonI = (CommandBarButtonForDisplay) commandBarButtons.get(i);
        if (buttonI == null) {
          if (commandBarActionIds[i] != null)
            return true;
        }
        else if (!buttonI.getActionId().equals(commandBarActionIds[i]))
          return true;
      }
      return false;
    }
   
    private boolean areAlternativeActionsChanged() {
      // Fetch command-bar alternative actions
      String[] commandBarAlternativeActionIds = CommandBarAttributes.getAlternateActions();
      int nbActions = commandBarAlternativeActionIds.length;
     
      if (nbActions != commandBarAlternateButtons.size())
        return true;
     
      for (int i=0; i<nbActions; ++i) {
        CommandBarButtonForDisplay buttonI = (CommandBarButtonForDisplay) commandBarAlternateButtons.get(i);
        if (buttonI == null) {
          if (commandBarAlternativeActionIds[i] != null)
            return true;
        }
        else if (!buttonI.getActionId().equals(commandBarAlternativeActionIds[i]))
          return true;
      }
      return false;
    }
   
    private boolean isModifierChanged() {
      return !modifierField.getKeyStroke().equals(CommandBarAttributes.getModifier());
    }
   
  private Collection<String> initCommandBarActionsList() {
    String[] commandBarActionIds = CommandBarAttributes.getActions();
    int nbCommandBarActionIds = commandBarActionIds.length;
    for (int i=0; i<nbCommandBarActionIds; ++i)
      commandBarButtons.add(CommandBarButtonForDisplay.create(commandBarActionIds[i]));
   
    commandBarButtonsList = new DynamicList<JButton>(commandBarButtons);
   
    // Set lists cells renderer
    commandBarButtonsList.setCellRenderer(new CommandBarButtonListCellRenderer());
    // Horizontal layout
    commandBarButtonsList.setLayoutOrientation(JList.HORIZONTAL_WRAP);
    // All buttons appear in one row
    commandBarButtonsList.setVisibleRowCount(1);
    // Drag operations are supported
    commandBarButtonsList.setDragEnabled(true);
    // Set transfer handler
    commandBarButtonsList.setTransferHandler(new TransferHandler(){
     
      @Override
      public int getSourceActions(JComponent c) {
        return MOVE;
      }
     
      @Override
      public Transferable createTransferable(JComponent c) {
        if (c instanceof JList) {
          JList list = (JList) c;
          return new TransferableButton((JButton) list.getSelectedValue());
        }
        return null;
      }
     
      @Override
      public void exportDone(JComponent c, Transferable t, int action) {
        if (action == TransferHandler.MOVE) {
          JList list = (JList) c;
          removeCommandBarButtonAtIndex(list.getSelectedIndex());
          componentChanged();
        }
      }
     
      @Override
      public boolean canImport(TransferHandler.TransferSupport support) {
        return support.isDataFlavorSupported(TransferableButton.buttonFlavor);
      }
     
      @Override
      public boolean importData(TransferHandler.TransferSupport support) {
        if (!canImport(support))
          return false;
        try {
          Point dropLocation = support.getDropLocation().getDropPoint();
          JButton button = (JButton) support.getTransferable().getTransferData(TransferableButton.buttonFlavor);
          int index = addCommandBarButtonAtLocation(dropLocation, button);
          commandBarButtonsList.ensureIndexIsVisible(index);
          commandBarButtonsList.repaint();
          return true;
        } catch (UnsupportedFlavorException e) {
          e.printStackTrace();
        } catch (IOException e) {
          e.printStackTrace();
        }
        return false;
      }
    });
   
    // Set list's background color
    commandBarButtonsList.setBackground(JBUTTON_BACKGROUND_COLOR);

    commandBarButtonsList.setDropMode(DropMode.INSERT);
   
    return Arrays.asList(commandBarActionIds);
  }
 
  private void removeCommandBarButtonAtIndex(int index) {
    commandBarButtons.remove(index);
    if (commandBarButtons.size() == 0) {
      commandBarButtons.add(null);
      commandBarButtonsList.setDropMode(DropMode.ON);
    }
    JButton alternateButtonAtIndex = commandBarAlternateButtons.remove(index);
    if (alternateButtonAtIndex != null)
      insertInOrder(commandBarAvailableButtons, alternateButtonAtIndex);
  }
 
  private int getNumberOfButtons() {
    int commandBarButtonsSize = commandBarButtons.size();
    return commandBarButtonsSize == 1 && commandBarButtons.get(0) == null ? 0 : commandBarButtonsSize;
  }
 
  private int addCommandBarButtonAtLocation(Point dropLocation, JButton button) {
    int index;
    if (getNumberOfButtons() == 0) {
      index = 0;
      commandBarButtons.set(index, button);
      commandBarAlternateButtons.add(index, null);
      commandBarButtonsList.setDropMode(DropMode.INSERT);
    }
    else {
      index = commandBarButtonsList.locationToIndex(dropLocation);
      index += dropLocation.x > commandBarButtonsList.indexToLocation(index).x + CommandBarButtonForDisplay.PREFERRED_SIZE.width/2 ? 1 : 0;
      commandBarButtons.add(index, button);
      commandBarAlternateButtons.add(index, null);
    }
    return index;
  }
 
  private Collection<String> initCommandBarAlternateActionsList() {
    String[] commandBarActionIds = CommandBarAttributes.getAlternateActions();
    int nbCommandBarActionIds = commandBarActionIds.length;
    for (int i=0; i<nbCommandBarActionIds; ++i)
      commandBarAlternateButtons.add(CommandBarButtonForDisplay.create(commandBarActionIds[i]));
   
    commandBarAlternateButtonsList = new DynamicList<JButton>(commandBarAlternateButtons);
   
    // Set lists cells renderer
    commandBarAlternateButtonsList.setCellRenderer(new CommandBarAlternativeButtonListRenderer());
    // Horizontal layout
    commandBarAlternateButtonsList.setLayoutOrientation(JList.HORIZONTAL_WRAP);
    // All buttons appear in one row
    commandBarAlternateButtonsList.setVisibleRowCount(1);
    // Drag operations are supported
    commandBarAlternateButtonsList.setDragEnabled(true);
    // Set transfer handler
    commandBarAlternateButtonsList.setTransferHandler(new TransferHandler() {
   
      @Override
      public int getSourceActions(JComponent c) {
        return MOVE;
      }
     
      @Override
      public Transferable createTransferable(JComponent c) {
        if (c instanceof JList) {
          JList list = (JList) c;
          return new TransferableButton((JButton) list.getSelectedValue());
        }
        return null;
      }
     
      @Override
      public void exportDone(JComponent c, Transferable t, int action) {
        if (action == TransferHandler.MOVE) {
          JList list = (JList) c;
          commandBarAlternateButtons.set(list.getSelectedIndex(), null);
          componentChanged();
        }
      }
     
      @Override
      public boolean canImport(TransferHandler.TransferSupport support) {
        return support.isDataFlavorSupported(TransferableButton.buttonFlavor);
      }
     
      @Override
      public boolean importData(TransferHandler.TransferSupport support) {
        if (!canImport(support))
          return false;
        try {
          Point dropLocation = support.getDropLocation().getDropPoint();
          int index = commandBarButtonsList.locationToIndex(dropLocation);
          JButton prevButton = commandBarAlternateButtons.get(index);
          if (prevButton != null)
            insertInOrder(commandBarAvailableButtons, prevButton);

          commandBarAlternateButtons.set(index, (JButton) support.getTransferable().getTransferData(TransferableButton.buttonFlavor));
          commandBarAlternateButtonsList.ensureIndexIsVisible(index);
          commandBarAlternateButtonsList.repaint();
          return true;
        } catch (UnsupportedFlavorException e) {
          e.printStackTrace();
        } catch (IOException e) {
          e.printStackTrace();
        }
        return false;
      }
    });
   
    // Set list's background color
    commandBarAlternateButtonsList.setBackground(JBUTTON_BACKGROUND_COLOR);
   
    commandBarAlternateButtonsList.setDropMode(DropMode.ON);
   
    return Arrays.asList(commandBarActionIds);
  }
 
  private void initActionsPoolList(Set<String> usedActions) {
    Iterator<String> actionIds = ActionManager.getActionIds();
    while(actionIds.hasNext()) {
            String actionId = actionIds.next();
            // Filter out actions that are currently used in the command bar, and those that are parameterized
      if (!usedActions.contains(actionId) && !ActionProperties.getActionDescriptor(actionId).isParameterized())
        insertInOrder(commandBarAvailableButtons, CommandBarButtonForDisplay.create(actionId));     
    }

    commandBarAvailableButtonsList = new DynamicHorizontalWrapList<JButton>(commandBarAvailableButtons, CommandBarButtonForDisplay.PREFERRED_SIZE.width, 6);
   
    commandBarAvailableButtonsList.setCellRenderer(new AvailableButtonCellListRenderer());
    commandBarAvailableButtonsList.setDragEnabled(true);
    commandBarAvailableButtonsList.setTransferHandler(new TransferHandler() {
   
      @Override
      public int getSourceActions(JComponent c) {
        return MOVE;
      }
     
      @Override
      public Transferable createTransferable(JComponent c) {
        if (c instanceof JList)
          return new TransferableButton((JButton) ((JList) c).getSelectedValue());
        return null;
      }
     
      @Override
      public void exportDone(JComponent c, Transferable t, int action) {
        if (action == TransferHandler.MOVE) {
          if (c instanceof JList)
            commandBarAvailableButtons.remove(((JList) c).getSelectedValue());
          componentChanged();
        }
      }
     
      @Override
      public boolean canImport(TransferHandler.TransferSupport support) {
        if (!support.isDataFlavorSupported(TransferableButton.buttonFlavor))
          return false;
        return true;
      }
     
      @Override
      public boolean importData(TransferHandler.TransferSupport support) {
        if (!canImport(support))
          return false;
        try {
          int insertedIndex = insertInOrder(commandBarAvailableButtons, (JButton) support.getTransferable().getTransferData(TransferableButton.buttonFlavor));
          commandBarAvailableButtonsList.ensureIndexIsVisible(insertedIndex);
          return true;
        }
        catch (UnsupportedFlavorException e) {
          e.printStackTrace();
        } catch (IOException e) {
          e.printStackTrace();
        }
        return false;
      }
    });
   
    commandBarAvailableButtonsList.setBackground(JBUTTON_BACKGROUND_COLOR);
   
    commandBarAvailableButtonsList.setDropMode(DropMode.ON);
  }
 
  protected JPanel createAvailableButtonsPanel() {
    JPanel panel = new JPanel(new GridLayout(1,0));
    panel.setBorder(BorderFactory.createTitledBorder(Translator.get("command_bar_customize_dialog.available_actions")));
   
    JScrollPane scrollPane = new JScrollPane(commandBarAvailableButtonsList, JScrollPane.VERTICAL_SCROLLBAR_AS_NEEDED, JScrollPane.HORIZONTAL_SCROLLBAR_NEVER);
    scrollPane.setBorder(null);
    panel.add(scrollPane);
   
    return panel;
  }
 
  private JPanel createCommandBarPanel() {
    YBoxPanel panel = new YBoxPanel();
    panel.setBorder(BorderFactory.createTitledBorder(Translator.get("preview")));
   
    panel.add(Box.createRigidArea(new Dimension(0, 5)));
   
    YBoxPanel listsPanel = new YBoxPanel();
    listsPanel.add(commandBarButtonsList);
    listsPanel.add(commandBarAlternateButtonsList);

    JScrollPane scrollPane = new JScrollPane(listsPanel, JScrollPane.VERTICAL_SCROLLBAR_NEVER, JScrollPane.HORIZONTAL_SCROLLBAR_ALWAYS);
    scrollPane.setBorder(null);
    panel.add(scrollPane);

    panel.add(Box.createRigidArea(new Dimension(0, 5)));
   
    panel.add(new JLabel("(" + Translator.get("command_bar_dialog.help") + ")"));
   
    panel.add(Box.createRigidArea(new Dimension(0, 5)));
   
    JPanel modifierPanel = new JPanel(new FlowLayout(FlowLayout.LEFT));
    modifierField = new RecordingKeyStrokeTextField(MODIFIER_FIELD_MAX_LENGTH, CommandBarAttributes.getModifier()) {
     
      @Override
            public void setText(String t) {
        super.setText(t);
        componentChanged();
      }
     
      @Override
            public void keyPressed(KeyEvent e) {
        int pressedKeyCode = e.getKeyCode();
        // Accept modifier keys only
        if (pressedKeyCode == KeyEvent.VK_CONTROL || pressedKeyCode == KeyEvent.VK_ALT
            || pressedKeyCode == KeyEvent.VK_META || pressedKeyCode == KeyEvent.VK_SHIFT)
          super.keyPressed(e);
      }
    };
   
    modifierPanel.add(new JLabel(Translator.get("command_bar_customize_dialog.modifier")));
    modifierPanel.add(modifierField);
    panel.add(modifierPanel);
   
    return panel;
  }
 
  private static class TransferableButton implements Transferable {
      public static DataFlavor buttonFlavor = new DataFlavor(CommandBarButtonForDisplay.class, null);
     
      private JButton button;
     
      public TransferableButton(JButton button) {
        this.button = button;
      }
     
      public Object getTransferData(DataFlavor flavor) throws UnsupportedFlavorException, IOException {
        return button;
      }
     
      public DataFlavor[] getTransferDataFlavors() {
        return new DataFlavor[] {buttonFlavor};
      }
   
      public boolean isDataFlavorSupported(DataFlavor flavor) {
        return buttonFlavor.equals(flavor);
      }
    }
 
  private static class CommandBarButtonListCellRenderer implements ListCellRenderer {
   
    public Component getListCellRendererComponent(JList list, Object value,
        int index, boolean isSelected, boolean cellHasFocus) {
      return value == null ? createBoxFiller() : (CommandBarButtonForDisplay) value;
        }
  }

  private static class CommandBarAlternativeButtonListRenderer implements ListCellRenderer {

    public Component getListCellRendererComponent(JList list, Object value,
        int index, boolean isSelected, boolean cellHasFocus) {
      return value == null ? createBoxFiller() : (CommandBarButtonForDisplay) value;
        }
  }

  private static class AvailableButtonCellListRenderer implements ListCellRenderer {

    public Component getListCellRendererComponent(JList list, Object value,
        int index, boolean isSelected, boolean cellHasFocus) {
     
      JPanel panel = new JPanel(new BorderLayout());
      CommandBarButtonForDisplay button = (CommandBarButtonForDisplay) value;
      panel.add(button, BorderLayout.CENTER);
      panel.setToolTipText(button.getToolTipText());
      return panel;
        }
  } 

  //////////////////////////
  ///// Helper methods /////
  //////////////////////////
 
  private static Filler createBoxFiller() {
    Box.Filler filler = (Filler) Box.createHorizontalGlue();
    filler.setPreferredSize(CommandBarButtonForDisplay.PREFERRED_SIZE);   
    return filler;
  }
 
  private static int insertInOrder(List<JButton> vector, JButton element) {
    if (vector.size() != 0) {
      int index = findPlace(vector, element, BUTTONS_COMPARATOR, 0, vector.size() - 1);
      vector.add(index, element);
      return index;
    }
    else {
      vector.add(element);
      return vector.size();
    }
  }
 
  private static int findPlace(List<JButton> vector, JButton element, Comparator<JButton> comparator, int first, int last) {
    if (comparator.compare(vector.get(last), element) < 0)
      return last + 1;
    if (comparator.compare(vector.get(first), element) > 0)
      return first;
    if (last - first == 1)
      return last;
   
    int middle = (first + last) / 2;
    int result = comparator.compare(vector.get(middle), element);
    return result > 0 ?
        findPlace(vector, element, comparator, first, middle) :
        findPlace(vector, element, comparator, middle, last);
  }
}
TOP

Related Classes of com.mucommander.ui.dialog.customization.CommandBarDialog$CommandBarButtonListCellRenderer

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.