content: /*
    This file is a part of Angry IP Scanner source code,
    see http://www.angryip.org/ for more information.
    Licensed under GPLv2.
   */
  package net.azib.ipscan.gui.actions;
  
  import net.azib.ipscan.config.Labels;
  import net.azib.ipscan.config.OpenersConfig;
  import net.azib.ipscan.config.OpenersConfig.Opener;
  import net.azib.ipscan.core.UserErrorException;
  import net.azib.ipscan.core.state.ScanningState;
  import net.azib.ipscan.core.state.StateMachine;
  import net.azib.ipscan.fetchers.FetcherRegistry;
  import net.azib.ipscan.gui.DetailsWindow;
  import net.azib.ipscan.gui.EditOpenersDialog;
  import net.azib.ipscan.gui.ResultTable;
  import net.azib.ipscan.gui.StatusBar;
  import org.eclipse.swt.SWT;
  import org.eclipse.swt.dnd.Clipboard;
  import org.eclipse.swt.dnd.TextTransfer;
  import org.eclipse.swt.dnd.Transfer;
  import org.eclipse.swt.widgets.Event;
  import org.eclipse.swt.widgets.Listener;
  import org.eclipse.swt.widgets.Menu;
  import org.eclipse.swt.widgets.MenuItem;
  
  /**
   * Commands and Context menu Actions.
   * All these operate on the items, selected in the results list.
   *
   * @author Anton Keks
   */
  public class CommandsMenuActions {
  	public Details details;
  	public Delete delete;
  	public Rescan rescan;
  	public CopyIP copyIP;
  	public CopyIPDetails copyIPDetails;
  	public ShowOpenersMenu showOpenersMenu;
  	public EditOpeners editOpeners;
  	public SelectOpener selectOpener;
  
  	public CommandsMenuActions(Details details, Delete delete, Rescan rescan, CopyIP copyIP, CopyIPDetails copyIPDetails, ShowOpenersMenu showOpenersMenu, EditOpeners editOpeners, SelectOpener selectOpener) {
  		this.details = details;
  		this.delete = delete;
  		this.rescan = rescan;
  		this.copyIP = copyIP;
  		this.copyIPDetails = copyIPDetails;
  		this.showOpenersMenu = showOpenersMenu;
  		this.editOpeners = editOpeners;
  		this.selectOpener = selectOpener;
  	}
  
  	/**
  	 * Checks that there is at least one item selected in the results list.
  	 */
  	static void checkSelection(ResultTable resultTable) {
  		if (resultTable.getItemCount() <= 0) {
  			throw new UserErrorException("commands.noResults");
  		}
  		else
  		if (resultTable.getSelectionIndex() < 0) {
  			throw new UserErrorException("commands.noSelection");
  		}
  	}
  
  	public static class Details implements Listener {
  		private final ResultTable resultTable;
  		private final DetailsWindow detailsWindow;
  		
  		public Details(ResultTable resultTable, DetailsWindow detailsWindow) {
  			this.resultTable = resultTable;
  			this.detailsWindow = detailsWindow;
  			resultTable.addListener(SWT.Traverse, this);
  			resultTable.addListener(SWT.MouseDoubleClick, this);
  		}
  
  		public void handleEvent(Event event) {
  			// activate only if something is selected
  			if (event.type == SWT.Selection || (resultTable.getSelectionIndex() >= 0 && (event.type == SWT.MouseDoubleClick || event.detail == SWT.TRAVERSE_RETURN))) {
  				event.doit = false;
  				checkSelection(resultTable);
  				detailsWindow.open(); 
  			}
  		}
  	}
  	
  	public static final class Delete implements Listener {
  		private final ResultTable resultTable;
  		private final StateMachine stateMachine;
  
  		public Delete(ResultTable resultTable, StateMachine stateMachine) {
  			this.resultTable = resultTable;
  			this.stateMachine = stateMachine;
  		}
  
  		public void handleEvent(Event event) {
  			// ignore other keys if this is a KeyDown event - 
  			// the same listener is used for several events
  			if (event.type == SWT.KeyDown && event.keyCode != SWT.DEL) return;
  			// deletion not allowed when scanning
  			if (!stateMachine.inState(ScanningState.IDLE)) return;
  			
  			int firstSelection = resultTable.getSelectionIndex();
  			if (firstSelection < 0) return;
  
  			resultTable.remove(resultTable.getSelectionIndices());
  			resultTable.setSelection(firstSelection);
  			event.widget = resultTable;
  			resultTable.notifyListeners(SWT.Selection, event);
  		}
  	}
  
  	public static final class Rescan implements Listener {
  		private final ResultTable resultTable;
  		private final StateMachine stateMachine;
  
  		public Rescan(ResultTable resultTable, StateMachine stateMachine) {
  			this.resultTable = resultTable;
  			this.stateMachine = stateMachine;
  		}
  
  		public void handleEvent(Event event) {
  			checkSelection(resultTable);
  			stateMachine.rescan();
  		}
  	}
  	
  	/**
  	 * Copies currently selected IP to the clipboard.
  	 * Used as both menu item listener and key down listener.
  	 */
  	public static final class CopyIP implements Listener {
  		private final ResultTable resultTable;
  
  		public CopyIP(ResultTable resultTable) {
  			this.resultTable = resultTable;
  		}
  
  		public void handleEvent(Event event) {
  			if (event.type == SWT.KeyDown) {
  				// if this is not Ctrl+C or nothing is selected, then simply do nothing
  				if ((event.keyCode != 'c' && event.stateMask != SWT.MOD1) || resultTable.getSelectionIndex() < 0)
  					return;
  			}
  			else {
  				// if selected from the menu, check selection
  				checkSelection(resultTable);
  			}
  			Clipboard clipboard = new Clipboard(event.display);
  			clipboard.setContents(new Object[] {resultTable.getItem(resultTable.getSelectionIndex()).getText()}, new Transfer[] {TextTransfer.getInstance()});
  			clipboard.dispose();
  		}
  	}
  	
  	public static final class CopyIPDetails implements Listener {
  		private final ResultTable resultTable;
  
  		public CopyIPDetails(ResultTable resultTable) {
  			this.resultTable = resultTable;
  		}
  
  		public void handleEvent(Event event) {
  			checkSelection(resultTable);
  			Clipboard clipboard = new Clipboard(event.display);
  			clipboard.setContents(new Object[] {resultTable.getSelectedResult().toString()}, new Transfer[] {TextTransfer.getInstance()});
  			clipboard.dispose();
  		}
  	}
  	
  	public static final class ShowOpenersMenu implements Listener {
  		
  		private final Listener openersSelectListener;
  		private final OpenersConfig openersConfig;
  
  		public ShowOpenersMenu(OpenersConfig openersConfig, SelectOpener selectOpener) {
  			this.openersConfig = openersConfig;
  			this.openersSelectListener = selectOpener;
  		}
  
  		public void handleEvent(Event event) {
  			Menu openersMenu = (Menu)event.widget;
  			MenuItem[] menuItems = openersMenu.getItems();
  			for (int i = 2; i < menuItems.length; i++) {
  				menuItems[i].dispose();
  			}
  			
  			// update menu items
  			int index = 0;
  			for (String name : openersConfig) {
  				MenuItem menuItem = new MenuItem(openersMenu, SWT.CASCADE);
  				
  				index++;
  				if (index <= 9) {
  					name += "\tCtrl+" + index;
  					menuItem.setAccelerator(SWT.MOD1 | ('0' + index));
  				}
  				
  				menuItem.setText(name);
  				menuItem.setData(index);
  				menuItem.addListener(SWT.Selection, openersSelectListener);
  			}
  
  		}
  	}
  		
  	public static final class EditOpeners implements Listener {
  		
  		private final FetcherRegistry fetcherRegistry;
  		private final OpenersConfig openersConfig;
  
  		public EditOpeners(FetcherRegistry fetcherRegistry, OpenersConfig openersConfig) {
  			this.fetcherRegistry = fetcherRegistry;
  			this.openersConfig = openersConfig;
  		}
  
  		public void handleEvent(Event event) {
  			new EditOpenersDialog(fetcherRegistry, openersConfig).open(); 
  		}
  	}
  	
  	public static final class SelectOpener implements Listener {
  		
  		private final StatusBar statusBar;
  		private final ResultTable resultTable;
  		private final OpenerLauncher openerLauncher;
  		private final OpenersConfig openersConfig;
  
  		public SelectOpener(OpenersConfig openersConfig, StatusBar statusBar, ResultTable resultTable, OpenerLauncher openerLauncher) {
  			this.openersConfig = openersConfig;
  			this.statusBar = statusBar;
  			this.resultTable = resultTable;
  			this.openerLauncher = openerLauncher;
  		}
  		
  		public void handleEvent(Event event) {
  			MenuItem menuItem = (MenuItem) event.widget;
  			String name = menuItem.getText();
  			int indexOf = name.lastIndexOf('\t');
  			if (indexOf >= 0) {
  				name = name.substring(0, indexOf);
  			}
  			Opener opener = openersConfig.getOpener(name);
  
  			int[] selectionIndices = resultTable.getSelectionIndices();
  			if (selectionIndices.length == 0)
  				throw new UserErrorException("commands.noSelection");
  
  			for (int i : selectionIndices) {
  				try {
  					statusBar.setStatusText(Labels.getLabel("state.opening") + name);
  					openerLauncher.launch(opener, i);
  					// wait a bit to make status visible
  					Thread.sleep(100);
  				}
  				catch (InterruptedException ignore) {}
  				finally {
  					statusBar.setStatusText(null);
  				}
  			}
  		}
  	}
  }
  