/******************************************************************************* * Copyright (c) 2013, 2016 SAP AG and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * * Contributors: * Tobias Pfeifer (SAP AG) - initial implementation * Thomas Wolf <thomas.wolf@paranor.ch> - Bug 460595 *******************************************************************************/ package org.eclipse.egit.ui.internal.rebase; import java.util.ArrayList; import java.util.Collections; import java.util.EnumMap; import java.util.List; import java.util.Map; import org.eclipse.egit.core.internal.rebase.RebaseInteractivePlan; import org.eclipse.egit.core.internal.rebase.RebaseInteractivePlan.ElementAction; import org.eclipse.egit.core.internal.rebase.RebaseInteractivePlan.ElementType; import org.eclipse.egit.core.internal.rebase.RebaseInteractivePlan.PlanElement; import org.eclipse.egit.ui.internal.UIIcons; import org.eclipse.egit.ui.internal.UIText; import org.eclipse.jface.bindings.keys.SWTKeySupport; import org.eclipse.jface.resource.ImageDescriptor; import org.eclipse.jface.resource.JFaceResources; import org.eclipse.jface.resource.LocalResourceManager; import org.eclipse.jface.viewers.ISelection; import org.eclipse.jface.viewers.IStructuredSelection; import org.eclipse.swt.SWT; import org.eclipse.swt.events.DisposeEvent; import org.eclipse.swt.events.DisposeListener; import org.eclipse.swt.events.SelectionAdapter; import org.eclipse.swt.events.SelectionEvent; import org.eclipse.swt.events.SelectionListener; import org.eclipse.swt.graphics.Image; import org.eclipse.swt.widgets.Composite; import org.eclipse.swt.widgets.ToolBar; import org.eclipse.swt.widgets.ToolItem; /** * Toolbar provider for editing rebase interactive steps */ public class RebaseInteractiveStepActionToolBarProvider { private static final int[] MOVE_ACCELERATORS = { SWT.MOD1 + SWT.ARROW_UP, SWT.MOD1 + SWT.ARROW_DOWN }; private ToolItem itemMoveUp; private ToolItem itemMoveDown; private final Map<RebaseInteractivePlan.ElementAction, ToolItem> rebaseActionItems = new EnumMap<>( RebaseInteractivePlan.ElementAction.class); private final Map<RebaseInteractivePlan.ElementAction, Integer> accelerators = new EnumMap<>( RebaseInteractivePlan.ElementAction.class); private final RebaseInteractiveView view; private final ToolBar theToolbar; private LocalResourceManager resources = new LocalResourceManager( JFaceResources.getResources()); /** * @return the theToolbar */ final ToolBar getTheToolbar() { return theToolbar; } /** * @param parent * @param style * @param view */ public RebaseInteractiveStepActionToolBarProvider(Composite parent, int style, RebaseInteractiveView view) { accelerators.put(ElementAction.EDIT, Integer.valueOf('E')); accelerators.put(ElementAction.FIXUP, Integer.valueOf('F')); accelerators.put(ElementAction.PICK, Integer.valueOf('P')); accelerators.put(ElementAction.REWORD, Integer.valueOf('R')); accelerators.put(ElementAction.SKIP, Integer.valueOf(SWT.DEL)); accelerators.put(ElementAction.SQUASH, Integer.valueOf('S')); this.theToolbar = new ToolBar(parent, style); this.view = view; createToolBarItems(); this.theToolbar.addDisposeListener(new DisposeListener() { @Override public void widgetDisposed(DisposeEvent e) { dispose(); } }); } private Image getImage(ImageDescriptor descriptor) { return (Image) this.resources.get(descriptor); } private void dispose() { resources.dispose(); } private String textFor(ElementAction action, String base) { int accelerator = getActionAccelerators().get(action).intValue(); return base + " (" + SWTKeySupport.getKeyFormatterForPlatform().format( //$NON-NLS-1$ SWTKeySupport.convertAcceleratorToKeyStroke(accelerator)) + ')'; } private String textFor(int idx, String base) { int accelerator = MOVE_ACCELERATORS[idx]; return base + " (" + SWTKeySupport.getKeyFormatterForPlatform().format( //$NON-NLS-1$ SWTKeySupport.convertAcceleratorToKeyStroke(accelerator)) + ')'; } private void createToolBarItems() { ToolItem itemPick = new ToolItem(theToolbar, SWT.RADIO); itemPick.setImage(getImage(UIIcons.CHERRY_PICK)); itemPick.addSelectionListener(new ActionSelectionListener( RebaseInteractivePlan.ElementAction.PICK)); itemPick.setText(UIText.RebaseInteractiveStepActionToolBarProvider_PickText); itemPick.setToolTipText(textFor(ElementAction.PICK, UIText.RebaseInteractiveStepActionToolBarProvider_PickDesc)); rebaseActionItems.put(ElementAction.PICK, itemPick); ToolItem itemSkip = new ToolItem(theToolbar, SWT.RADIO); itemSkip.setImage(getImage(UIIcons.REBASE_SKIP)); itemSkip.addSelectionListener(new ActionSelectionListener( RebaseInteractivePlan.ElementAction.SKIP)); itemSkip.setText(UIText.RebaseInteractiveStepActionToolBarProvider_SkipText); itemSkip.setToolTipText(textFor(ElementAction.SKIP, UIText.RebaseInteractiveStepActionToolBarProvider_SkipDesc)); rebaseActionItems.put(ElementAction.SKIP, itemSkip); ToolItem itemEdit = new ToolItem(theToolbar, SWT.RADIO); itemEdit.setImage(getImage(UIIcons.EDITCONFIG)); itemEdit.addSelectionListener(new ActionSelectionListener( RebaseInteractivePlan.ElementAction.EDIT)); itemEdit.setText(UIText.RebaseInteractiveStepActionToolBarProvider_EditText); itemEdit.setToolTipText(textFor(ElementAction.EDIT, UIText.RebaseInteractiveStepActionToolBarProvider_EditDesc)); rebaseActionItems.put(ElementAction.EDIT, itemEdit); ToolItem itemSquash = new ToolItem(theToolbar, SWT.RADIO); itemSquash.setImage(getImage(UIIcons.SQUASH_UP)); itemSquash.addSelectionListener(new ActionSelectionListener( RebaseInteractivePlan.ElementAction.SQUASH)); itemSquash.setText( UIText.RebaseInteractiveStepActionToolBarProvider_SquashText); itemSquash.setToolTipText(textFor(ElementAction.SQUASH, UIText.RebaseInteractiveStepActionToolBarProvider_SquashDesc)); rebaseActionItems.put(ElementAction.SQUASH, itemSquash); ToolItem itemFixup = new ToolItem(theToolbar, SWT.RADIO); itemFixup.setImage(getImage(UIIcons.FIXUP_UP)); itemFixup.addSelectionListener(new ActionSelectionListener( RebaseInteractivePlan.ElementAction.FIXUP)); itemFixup.setText( UIText.RebaseInteractiveStepActionToolBarProvider_FixupText); itemFixup.setToolTipText(textFor(ElementAction.FIXUP, UIText.RebaseInteractiveStepActionToolBarProvider_FixupDesc)); rebaseActionItems.put(ElementAction.FIXUP, itemFixup); ToolItem itemReword = new ToolItem(theToolbar, SWT.RADIO); itemReword.setImage(getImage(UIIcons.REWORD)); itemReword.addSelectionListener(new ActionSelectionListener( RebaseInteractivePlan.ElementAction.REWORD)); itemReword.setText( UIText.RebaseInteractiveStepActionToolBarProvider_RewordText); itemReword.setToolTipText(textFor(ElementAction.REWORD, UIText.RebaseInteractiveStepActionToolBarProvider_RewordDesc)); rebaseActionItems.put(ElementAction.REWORD, itemReword); new ToolItem(theToolbar, SWT.SEPARATOR); itemMoveUp = new ToolItem(theToolbar, SWT.NONE); itemMoveUp.setImage(getImage(UIIcons.ELCL16_PREVIOUS)); itemMoveUp.setText( UIText.RebaseInteractiveStepActionToolBarProvider_MoveUpText); itemMoveUp.setToolTipText(textFor(0, UIText.RebaseInteractiveStepActionToolBarProvider_MoveUpDesc)); itemMoveUp.addSelectionListener(new SelectionAdapter() { @Override public void widgetSelected(SelectionEvent e) { moveUp(); view.planTreeViewer.getControl().setFocus(); } }); itemMoveDown = new ToolItem(theToolbar, SWT.NONE); itemMoveDown.setImage(getImage(UIIcons.ELCL16_NEXT)); itemMoveDown.setText( UIText.RebaseInteractiveStepActionToolBarProvider_MoveDownText); itemMoveDown.setToolTipText(textFor(1, UIText.RebaseInteractiveStepActionToolBarProvider_MoveDownDesc)); itemMoveDown.addSelectionListener(new SelectionAdapter() { @Override public void widgetSelected(SelectionEvent e) { moveDown(); view.planTreeViewer.getControl().setFocus(); } }); } private class ActionSelectionListener implements SelectionListener { private final RebaseInteractivePlan.ElementAction type; ActionSelectionListener(final RebaseInteractivePlan.ElementAction action) { this.type = action; } @Override public void widgetSelected(SelectionEvent e) { List<RebaseInteractivePlan.PlanElement> selected = getSelectedRebaseTodoLines(); if (selected == null || selected.isEmpty()) return; ElementAction typeToSet = type; if (type != ElementAction.PICK) { boolean allItemsHaveTargetType = true; for (RebaseInteractivePlan.PlanElement element : selected) allItemsHaveTargetType &= element.getPlanElementAction() == type; if (allItemsHaveTargetType) { typeToSet = ElementAction.PICK; rebaseActionItems.get(ElementAction.PICK).setSelection(true); if (e.getSource() instanceof ToolItem) ((ToolItem) e.getSource()).setSelection(false); } } for (RebaseInteractivePlan.PlanElement element : selected) element.setPlanElementAction(typeToSet); mapActionItemsToSelection(view.planTreeViewer.getSelection()); view.planTreeViewer.getControl().setFocus(); } @Override public void widgetDefaultSelected(SelectionEvent e) { widgetSelected(e); } } /** * Returns the current selected entries in * {@link RebaseInteractiveView#planTreeViewer} of type * {@link org.eclipse.egit.core.internal.rebase.RebaseInteractivePlan.PlanElement} * * @return a {@link List}< * {@link org.eclipse.egit.core.internal.rebase.RebaseInteractivePlan.PlanElement} * > as the current selection. */ protected List<RebaseInteractivePlan.PlanElement> getSelectedRebaseTodoLines() { IStructuredSelection selection = (IStructuredSelection) view.planTreeViewer .getSelection(); List<RebaseInteractivePlan.PlanElement> planEntries = new ArrayList<>( selection.size()); @SuppressWarnings("unchecked") List<RebaseInteractivePlan.PlanElement> candidates = selection.toList(); for (Object candidate : candidates) { if (candidate instanceof RebaseInteractivePlan.PlanElement) planEntries.add((RebaseInteractivePlan.PlanElement) candidate); } return planEntries; } void mapActionItemsToSelection(ISelection selection) { setMoveItemsEnabled(false); if (selection == null || selection.isEmpty()) { if (theToolbar.isEnabled()) theToolbar.setEnabled(false); unselectAllActionItemsExecpt(null); return; } if (selection instanceof IStructuredSelection) { IStructuredSelection structured = (IStructuredSelection) selection; Object obj = structured.getFirstElement(); if (!(obj instanceof PlanElement)) return; PlanElement firstSelectedEntry = (PlanElement) obj; PlanElement lastSelectedEntry = firstSelectedEntry; ElementAction type = firstSelectedEntry.getPlanElementAction(); boolean singleTypeSelected = true; if (!theToolbar.isEnabled() && !view.getCurrentPlan().hasRebaseBeenStartedYet()) theToolbar.setEnabled(true); if (structured.size() > 1) { // multi selection for (Object selectedObj : structured.toList()) { if (!(selectedObj instanceof PlanElement)) continue; PlanElement entry = (PlanElement) selectedObj; lastSelectedEntry = entry; if (type != entry.getPlanElementAction()) { singleTypeSelected = false; } } } if (singleTypeSelected) unselectAllActionItemsExecpt(type); else unselectAllActionItemsExecpt(null); enableMoveButtons(firstSelectedEntry, lastSelectedEntry); } } private void enableMoveButtons( PlanElement firstSelectedEntry, PlanElement lastSelectedEntry) { List<PlanElement> list = view.getCurrentPlan().getList(); List<PlanElement> stepList = new ArrayList<>(); for (PlanElement planElement : list) { if (!planElement.isComment()) stepList.add(planElement); } int firstEntryIndex = stepList.indexOf(firstSelectedEntry); int lastEntryIndex = stepList.indexOf(lastSelectedEntry); if (!RebaseInteractivePreferences.isOrderReversed()) { itemMoveUp.setEnabled(firstEntryIndex > 0); itemMoveDown.setEnabled(lastEntryIndex < stepList.size() - 1); } else { itemMoveUp.setEnabled(firstEntryIndex < stepList.size() - 1); itemMoveDown.setEnabled(lastEntryIndex > 0); } } private void unselectAllActionItemsExecpt(ElementAction action) { for (Map.Entry<ElementAction, ToolItem> entry : rebaseActionItems .entrySet()) { entry.getValue().setSelection(entry.getKey() == action); } } private void setMoveItemsEnabled(boolean enabled) { itemMoveDown.setEnabled(enabled); itemMoveUp.setEnabled(enabled); } void moveUp() { List<PlanElement> selectedRebaseTodoLines = getSelectedRebaseTodoLines(); for (PlanElement planElement : selectedRebaseTodoLines) { if (planElement.getElementType() != ElementType.TODO) return; if (!RebaseInteractivePreferences.isOrderReversed()) view.getCurrentPlan().moveTodoEntryUp(planElement); else view.getCurrentPlan().moveTodoEntryDown(planElement); mapActionItemsToSelection(view.planTreeViewer.getSelection()); } } void moveDown() { List<PlanElement> selectedRebaseTodoLines = getSelectedRebaseTodoLines(); Collections.reverse(selectedRebaseTodoLines); for (PlanElement planElement : selectedRebaseTodoLines) { if (planElement.getElementType() != ElementType.TODO) return; if (!RebaseInteractivePreferences.isOrderReversed()) view.getCurrentPlan().moveTodoEntryDown(planElement); else view.getCurrentPlan().moveTodoEntryUp(planElement); mapActionItemsToSelection(view.planTreeViewer.getSelection()); } } Map<ElementAction, Integer> getActionAccelerators() { return accelerators; } int[] getMoveAccelerators() { return MOVE_ACCELERATORS; } }