/******************************************************************************* * 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(1, false)); GridData buttonContainerData = new GridData(SWT.FILL, SWT.CENTER, true, true); buttonContainerData.minimumWidth = 40; buttonContainer.setLayoutData(buttonContainerData); btnUp = new Button(buttonContainer, SWT.PUSH); GridData btnUpData = new GridData(SWT.LEFT, SWT.BOTTOM, true, false); 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, true, false); 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(2, false); layout.verticalSpacing = 10; layout.marginTop = 10; setLayout(layout); setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true)); } 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; } }