Project: gmc
/*******************************************************************************
 * Copyright (c) 2006-2011 Gluster, Inc. <http://www.gluster.com> 
 * This file is part of Gluster Management Console. 
 * 
 * Gluster Management Console 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. 
 * 
 * Gluster Management Console 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 org.gluster.storage.management.console.dialogs; 
 
import java.util.ArrayList; 
import java.util.HashSet; 
import java.util.List; 
import java.util.Set; 
 
import org.eclipse.jface.viewers.ITableLabelProvider; 
import org.eclipse.swt.SWT; 
import org.eclipse.swt.events.KeyAdapter; 
import org.eclipse.swt.events.KeyEvent; 
import org.eclipse.swt.events.SelectionAdapter; 
import org.eclipse.swt.events.SelectionEvent; 
import org.eclipse.swt.layout.GridData; 
import org.eclipse.swt.layout.GridLayout; 
import org.eclipse.swt.widgets.Button; 
import org.eclipse.swt.widgets.Composite; 
import org.eclipse.swt.widgets.Label; 
import org.eclipse.swt.widgets.TableItem; 
import org.eclipse.swt.widgets.Text; 
import org.gluster.storage.management.console.IImageKeys; 
import org.gluster.storage.management.console.TableLabelProviderAdapter; 
import org.gluster.storage.management.console.utils.EntityViewerFilter; 
import org.gluster.storage.management.console.utils.GUIHelper; 
import org.gluster.storage.management.core.model.Brick; 
import org.gluster.storage.management.core.model.Brick.BRICK_STATUS; 
import org.gluster.storage.management.core.model.Device; 
import org.gluster.storage.management.core.utils.NumberUtil; 
 
import com.richclientgui.toolbox.duallists.CustomTableDualListComposite; 
import com.richclientgui.toolbox.duallists.DualListComposite.ListContentChangedListener; 
import com.richclientgui.toolbox.duallists.IRemovableContentProvider; 
import com.richclientgui.toolbox.duallists.RemovableContentProvider; 
import com.richclientgui.toolbox.duallists.TableColumnData; 
 
public class BricksSelectionPage extends Composite { 
 private enum DISK_TABLE_COLUMN_INDICES { 
  SERVER, BRICK_DIRECTORY, FREE_SPACE, TOTAL_SPACE 
 
 
 private static final String[] DISK_TABLE_COLUMNS_NAMES = { "Server""Brick Directory""Free Space (GB)"
   "Total Space (GB)" }; 
 
 private GUIHelper guiHelper = GUIHelper.getInstance(); 
 private CustomTableDualListComposite<Device> dualTableViewer; 
 private Text filterText; 
 // This list keeps track of the order of the disks as user changes the same by clicking on up/down arrow buttons 
 private List<Device> chosenDevices = new ArrayList<Device>(); 
 
 private IRemovableContentProvider<Device> chosenBricksContentProvider; 
 
 private Button btnUp; 
 
 private Button btnDown; 
 
 public BricksSelectionPage(final Composite parent, int style, List<Device> allDevices, List<Device> selectedDevices, 
   String volumeName) { 
  super(parent, style); 
 
  createPage(allDevices, selectedDevices, volumeName); 
 
  parent.layout(); 
 
 
 public void addDiskSelectionListener(ListContentChangedListener<Device> listener) { 
  dualTableViewer.addChosenListChangedSelectionListener(listener); 
 
 
 private TableLabelProviderAdapter getDiskLabelProvider(final String volumeName) { 
  return new TableLabelProviderAdapter() { 
 
   @Override 
   public String getColumnText(Object element, int columnIndex) { 
    if (!(element instanceof Device)) { 
     return null
    
 
    Device device = (Device) element; 
    return (columnIndex == DISK_TABLE_COLUMN_INDICES.SERVER.ordinal() ? device.getServerName() 
      : columnIndex == DISK_TABLE_COLUMN_INDICES.BRICK_DIRECTORY.ordinal() ? device.getMountPoint() 
        "/" + volumeName 
        : columnIndex == DISK_TABLE_COLUMN_INDICES.FREE_SPACE.ordinal() ? NumberUtil 
          .formatNumber((device.getFreeSpace() / 1024)) 
          : columnIndex == DISK_TABLE_COLUMN_INDICES.TOTAL_SPACE.ordinal() ? NumberUtil 
            .formatNumber((device.getSpace() / 1024)) : "Invalid"); 
   
  }; 
 
 
 private void createPage(List<Device> allDevice, List<Device> selectedDevice, String volumeName) { 
  setupPageLayout(); 
 
  filterText = guiHelper.createFilterText(this); 
  new Label(this, SWT.NONE); 
 
  createDualTableViewer(allDevice, selectedDevice, volumeName); 
  createFilter(filterText, false); // attach filter text to the dual table viewer for auto-filtering 
 
  Composite buttonContainer = new Composite(this, SWT.NONE); 
  buttonContainer.setLayout(new GridLayout(1false)); 
  GridData buttonContainerData = new GridData(SWT.FILL, SWT.CENTER, truetrue); 
  buttonContainerData.minimumWidth = 40
  buttonContainer.setLayoutData(buttonContainerData); 
 
  btnUp = new Button(buttonContainer, SWT.PUSH); 
  GridData btnUpData = new GridData(SWT.LEFT, SWT.BOTTOM, truefalse); 
  btnUpData.minimumWidth = 30
  btnUp.setLayoutData(btnUpData); 
  btnUp.setImage(guiHelper.getImage(IImageKeys.ARROW_UP_16x16)); 
  btnUp.addSelectionListener(new SelectionAdapter() { 
 
   @Override 
   public void widgetSelected(SelectionEvent e) { 
    chosenDevices = getChosenDevices(); 
    List<Device> selectedDevices = getSelectedChosenDevices(); 
 
    chosenBricksContentProvider.removeElements(chosenDevices); 
    for (Device device : selectedDevices) { 
     int index = chosenDevices.indexOf(device); 
     Device deviceAbove = chosenDevices.get(index - 1); 
     chosenDevices.set(index - 1, device); 
     chosenDevices.set(index, deviceAbove); 
    
    chosenBricksContentProvider.addElements(chosenDevices); 
    dualTableViewer.refreshChosenViewer(); 
    updateButtons(); 
   
  }); 
 
  btnDown = new Button(buttonContainer, SWT.PUSH); 
  GridData btnDownData = new GridData(SWT.LEFT, SWT.TOP, truefalse); 
  btnDownData.minimumWidth = 30
  btnDown.setLayoutData(btnDownData); 
  btnDown.setImage(guiHelper.getImage(IImageKeys.ARROW_DOWN_16x16)); 
  btnDown.addSelectionListener(new SelectionAdapter() { 
 
   @Override 
   public void widgetSelected(SelectionEvent e) { 
 
    chosenDevices = getChosenDevices(); 
    List<Device> selectedDevices = getSelectedChosenDevices(); 
 
    chosenBricksContentProvider.removeElements(chosenDevices); 
    for (Device disk : selectedDevices) { 
     int index = chosenDevices.indexOf(disk); 
     Device deviceBelow = chosenDevices.get(index + 1); 
     chosenDevices.set(index + 1, disk); 
     chosenDevices.set(index, deviceBelow); 
    
    chosenBricksContentProvider.addElements(chosenDevices); 
    dualTableViewer.refreshChosenViewer(); 
    updateButtons(); 
 
   
  }); 
 
 
 private List<Device> getSelectedChosenDevices() { 
  TableItem[] selectedItems = dualTableViewer.getChosenTable().getSelection(); 
  List<Device> selectedDevices = new ArrayList<Device>(); 
  for (TableItem item : selectedItems) { 
   selectedDevices.add((Device) item.getData()); 
  
  return selectedDevices; 
 
 
 private void createFilter(final Text filterText, boolean caseSensitive) { 
  final String initialFilterString = filterText.getText(); 
 
  final EntityViewerFilter filter = new EntityViewerFilter(initialFilterString, caseSensitive); 
  // On every keystroke inside the text field, update the filter string 
  filterText.addKeyListener(new KeyAdapter() { 
   private String filterString = initialFilterString; 
 
   @Override 
   public void keyReleased(KeyEvent e) { 
    String enteredString = filterText.getText(); 
    if (enteredString.equals(filterString)) { 
     // Filter string has not changed. don't do anything 
     return
    
 
    // Update filter string 
    filterString = enteredString; 
    filter.setFilterString(filterString); 
 
    // Refresh viewer with newly filtered content 
    dualTableViewer.refreshAvailableViewer(); 
    dualTableViewer.refreshChosenViewer(); 
   
  }); 
 
  dualTableViewer.setAvailableViewerFilter(filter); 
  dualTableViewer.setChosenViewerFilter(filter); 
 
 
 private void createDualTableViewer(List<Device> allDevices, List<Device> selectedDevices, String volumeName) { 
  TableColumnData[] columnData = createColumnData(); 
  ITableLabelProvider diskLabelProvider = getDiskLabelProvider(volumeName); 
 
  dualTableViewer = new CustomTableDualListComposite<Device>(this, SWT.NONE, columnData, columnData); 
 
  dualTableViewer.setViewerLabels("Available:""Selected:"); 
 
  dualTableViewer.setAvailableTableLinesVisible(false); 
  dualTableViewer.setAvailableTableHeaderVisible(true); 
  dualTableViewer.setAvailableContentProvider(new RemovableContentProvider<Device>(getAvailableDevice(allDevices, 
    selectedDevices))); 
  dualTableViewer.setAvailableLabelProvider(diskLabelProvider); 
 
  dualTableViewer.setChosenTableLinesVisible(true); 
  dualTableViewer.setChosenTableHeaderVisible(true); 
 
  chosenBricksContentProvider = new RemovableContentProvider<Device>(selectedDevices); 
  dualTableViewer.setChosenContentProvider(chosenBricksContentProvider); 
  dualTableViewer.setChosenLabelProvider(diskLabelProvider); 
 
  dualTableViewer.getChosenTable().addSelectionListener(new SelectionAdapter() { 
   /*
    * (non-Javadoc) 
    *  
    * @see org.eclipse.swt.events.SelectionAdapter#widgetSelected(org.eclipse.swt.events.SelectionEvent) 
    */
 
   @Override 
   public void widgetSelected(SelectionEvent e) { 
    updateButtons(); 
   
  }); 
 
 
 private void updateButtons() { 
  btnUp.setEnabled(true); 
  btnDown.setEnabled(true); 
  List<Device> selectedChosenDevices = getSelectedChosenDevices(); 
  List<Device> chosenDevices = getChosenDevices(); 
  for (Device device : selectedChosenDevices) { 
   int index = chosenDevices.indexOf(device); 
   if (index == 0) { 
    btnUp.setEnabled(false); 
   
   if (index == chosenDevices.size() - 1) { 
    btnDown.setEnabled(false); 
   
  
 
 
 /**
  * @param allDevices 
  * @param selectedDevices 
  * @return 
  */
 
 private List<Device> getAvailableDevice(List<Device> allDevices, List<Device> selectedDevices) { 
  List<Device> availableDevices = new ArrayList<Device>(); 
  for (Device device : allDevices) { 
   if (!selectedDevices.contains(device)) { 
    availableDevices.add(device); 
   
  
  return availableDevices; 
 
 
 private TableColumnData[] createColumnData() { 
  DISK_TABLE_COLUMN_INDICES[] columns = DISK_TABLE_COLUMN_INDICES.values(); 
  TableColumnData[] columnData = new TableColumnData[columns.length]; 
  int columnNum; 
  for (DISK_TABLE_COLUMN_INDICES column : columns) { 
   columnNum = column.ordinal(); 
   columnData[columnNum] = new TableColumnData(columnNum, DISK_TABLE_COLUMNS_NAMES[columnNum], 100); 
  
  return columnData; 
 
 
 private void setupPageLayout() { 
  final GridLayout layout = new GridLayout(2false); 
  layout.verticalSpacing = 10
  layout.marginTop = 10
  setLayout(layout); 
 
  setLayoutData(new GridData(SWT.FILL, SWT.FILL, truetrue)); 
 
 
 public List<Device> getChosenDevices() { 
  Object[] devicesArr = chosenBricksContentProvider.getElements(dualTableViewer); 
  if (devicesArr != null) { 
   List<Device> devices = new ArrayList<Device>(); 
   for (Object device : devicesArr) { 
    devices.add((Device) device); 
   
   return devices; 
  
  return null
 
 
 public Set<Brick> getChosenBricks(String volumeName) { 
  Object[] bricksArr = chosenBricksContentProvider.getElements(dualTableViewer); 
 
  if (bricksArr != null) { 
   Set<Brick> bricks = new HashSet<Brick>(); 
   for (Object device : bricksArr) { 
    bricks.add(new Brick(((Device) device).getServerName(), BRICK_STATUS.ONLINE, ((Device) device) 
      .getMountPoint() + "/" + volumeName)); // Assumption mount point is not having trailing "/"  
   
   return bricks; 
  
  return null
 
 
}