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;
  
  import net.azib.ipscan.config.GUIConfig;
  import net.azib.ipscan.config.GUIConfig.DisplayMethod;
  import net.azib.ipscan.config.Labels;
  import net.azib.ipscan.config.ScannerConfig;
  import net.azib.ipscan.core.state.StateMachine;
  import net.azib.ipscan.gui.actions.CommandsMenuActions.Delete;
  import net.azib.ipscan.gui.actions.ToolsActions.SelectDead;
  import net.azib.ipscan.gui.actions.ToolsActions.SelectWithoutPorts;
  import net.azib.ipscan.gui.actions.ToolsActions.TableSelection;
  import net.azib.ipscan.gui.util.LayoutHelper;
  import org.eclipse.swt.SWT;
  import org.eclipse.swt.graphics.Color;
  import org.eclipse.swt.layout.FormAttachment;
  import org.eclipse.swt.widgets.*;
  
  import static net.azib.ipscan.config.GUIConfig.DisplayMethod.PORTS;
  import static net.azib.ipscan.gui.util.LayoutHelper.formData;
  
  /**
   * The status bar of the main window.
   *
   * @author Anton Keks
   */
  public class StatusBar {
  	private Composite composite;
  	private Label statusText;
  	private Label displayMethodText;
  	private Label threadsText;
  	private boolean maxThreadsReachedBefore;
  	private ProgressBar progressBar;
  	
  	private ScannerConfig scannerConfig;
  	private GUIConfig guiConfig;
  	private StateMachine stateMachine;
  	private ResultTable resultTable;
  
  	public StatusBar(Shell shell, GUIConfig guiConfig, ScannerConfig scannerConfig, ResultTable resultTable, StateMachine stateMachine) {
  		this.guiConfig = guiConfig;
  		this.scannerConfig = scannerConfig;
  		this.stateMachine = stateMachine;
  		this.resultTable = resultTable;
  		this.resultTable.addListener(SWT.Selection, new TableSelection(this, stateMachine));
  		
  		composite = new Composite(shell, SWT.NONE);
  		composite.setLayoutData(formData(new FormAttachment(0), new FormAttachment(100), null, new FormAttachment(100)));
  		
  		composite.setLayout(LayoutHelper.formLayout(1, 1, 2));
  		
  		statusText = new Label(composite, SWT.BORDER);
  		statusText.setLayoutData(formData(new FormAttachment(0), new FormAttachment(35), new FormAttachment(0), new FormAttachment(100)));
  		setStatusText(null);
  		
  		displayMethodText = new Label(composite, SWT.BORDER);
  		displayMethodText.setText(Labels.getLabel("text.display." + PORTS));
  		displayMethodText.pack();
  		displayMethodText.setLayoutData(formData(displayMethodText.getSize().x, SWT.DEFAULT, new FormAttachment(statusText), null, new FormAttachment(0), new FormAttachment(100)));
  		displayMethodText.addListener(SWT.MouseDown, new DisplayModeChangeListener());
  		updateConfigText();
  
  		threadsText = new Label(composite, SWT.BORDER);
  		setRunningThreads(Math.min(scannerConfig.maxThreads, 200)); // this should set the longest possible text		
  		threadsText.pack(); // calculate the width
  		threadsText.setLayoutData(formData(threadsText.getSize().x, SWT.DEFAULT, new FormAttachment(displayMethodText), null, new FormAttachment(0), new FormAttachment(100)));
  		setRunningThreads(0); // set back to 0 at startup
  		
  		progressBar = new ProgressBar(composite, SWT.BORDER);
  		progressBar.setLayoutData(formData(new FormAttachment(threadsText), new FormAttachment(100, 0), new FormAttachment(0), new FormAttachment(100)));
  		progressBar.setSelection(0);
  	}
  	
  	/**
  	 * Updates config text according to the latest changes in the GlobalConfig
  	 */
  	public void updateConfigText() {
  		displayMethodText.setText(Labels.getLabel("text.display." + guiConfig.displayMethod));
  	}
  
  	/**
  	 * Used for the positioning of the controls in the MainWindow
  	 */
  	Composite getComposite() {
  		return composite;
  	}
  	
  	/**
  	 * @return true if the underlying widgets are disposed
  	 */
  	public boolean isDisposed() {
  		return composite.isDisposed();
  	}
  	
  	/**
  	 * Sets the status bar text displayed to the user.
  	 * @param statusText the text to set, null to use the default text (Ready)
  	 */
  	public void setStatusText(String statusText) {
  		if (statusText == null) {
  			statusText = Labels.getLabel("state.ready"); 
  		}
  		if (!this.statusText.isDisposed())
  			this.statusText.setText(statusText);
  	}
  
  	public void setRunningThreads(int runningThreads) {
  		if (!threadsText.isDisposed()) { 
  			boolean maxThreadsReached = runningThreads == scannerConfig.maxThreads;
  			if (maxThreadsReachedBefore || maxThreadsReached) {
  				Color newColor = threadsText.getDisplay().getSystemColor(maxThreadsReached ? SWT.COLOR_RED : SWT.COLOR_WIDGET_FOREGROUND);
  				threadsText.setForeground(newColor);
  			}
  			maxThreadsReachedBefore = maxThreadsReached;
  			
  			threadsText.setText(Labels.getLabel("text.threads") + runningThreads + 
  					(maxThreadsReached ? Labels.getLabel("text.threads.max") : ""));
  		}
  	}
  	
  	public void setProgress(int progress) {
  		if (!progressBar.isDisposed())
  			progressBar.setSelection(progress);
  	}
  	
  	public Shell getShell() {
  		return composite.getShell();
  	}
  	
  	public void setEnabled(boolean enabled) {
  		// enable/disable interactive controls on the status bar
  		displayMethodText.setEnabled(enabled);
  	}
  
  	class DisplayModeChangeListener implements Listener {
  		private Menu popupMenu;
  
  		private void createPopupMenu() {
  			popupMenu = new Menu(getShell(), SWT.POP_UP);
  			for (DisplayMethod displayMethod : DisplayMethod.values()) {
  				MenuItem item = new MenuItem(popupMenu, 0);
  				item.setText(Labels.getLabel("text.display." + displayMethod));
  				item.setData(displayMethod);
  				item.addListener(SWT.Selection, this);
  			}
  		}
  
  		public void handleEvent(Event event) {
  			// user clicked the config text, lets ask the display options
  			if (event.type == SWT.MouseDown) {
  				if (popupMenu == null) createPopupMenu();
  				popupMenu.setVisible(true);
  			}
  			// handle menu item selection
  			else if (event.type == SWT.Selection) {
  				// remember the selected display method
  				guiConfig.displayMethod = (DisplayMethod) event.widget.getData();
  				updateConfigText();
  				if (!resultTable.getScanningResults().areResultsAvailable()) return;
  				switch (guiConfig.displayMethod) {
  					case ALIVE: {
  						new SelectDead(resultTable).handleEvent(event);
  						new Delete(resultTable, stateMachine).handleEvent(event);
  						break;
  					}
  					case PORTS: {
  						new SelectWithoutPorts(resultTable).handleEvent(event);
  						new Delete(resultTable, stateMachine).handleEvent(event);
  						break;
  					}
  				}
  			}
  		}
  	}
  }
  