Skip to content

Instantly share code, notes, and snippets.

@lenards
Created July 12, 2010 16:31
Show Gist options
  • Save lenards/472682 to your computer and use it in GitHub Desktop.
Save lenards/472682 to your computer and use it in GitHub Desktop.
package org.iplantc.de.client.views;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import org.iplantc.de.client.ErrorHandler;
import org.iplantc.de.client.EventBus;
import org.iplantc.de.client.I18N;
import org.iplantc.de.client.events.disk.mgmt.DiskResourceDeletedEvent;
import org.iplantc.de.client.events.disk.mgmt.DiskResourceDeletedEventHandler;
import org.iplantc.de.client.events.disk.mgmt.DiskResourceRenamedEvent;
import org.iplantc.de.client.events.disk.mgmt.DiskResourceRenamedEventHandler;
import org.iplantc.de.client.events.disk.mgmt.FileMovedEvent;
import org.iplantc.de.client.events.disk.mgmt.FileMovedEventHandler;
import org.iplantc.de.client.events.disk.mgmt.FileSaveAsEvent;
import org.iplantc.de.client.events.disk.mgmt.FileSaveAsEventHandler;
import org.iplantc.de.client.events.disk.mgmt.FileUploadedEvent;
import org.iplantc.de.client.events.disk.mgmt.FileUploadedEventHandler;
import org.iplantc.de.client.events.disk.mgmt.FolderCreatedEvent;
import org.iplantc.de.client.events.disk.mgmt.FolderCreatedEventHandler;
import org.iplantc.de.client.images.Resources;
import org.iplantc.de.client.models.DiskResource;
import org.iplantc.de.client.models.File;
import org.iplantc.de.client.models.Folder;
import org.iplantc.de.client.models.UserInfo;
import org.iplantc.de.client.services.FolderServices;
import org.iplantc.de.client.utils.TreeStoreWrapper;
import org.iplantc.de.client.views.dialogs.IPlantDialog;
import org.iplantc.de.client.views.panels.AddFolderDialogPanel;
import org.iplantc.de.client.views.panels.RenameFileDialogPanel;
import org.iplantc.de.client.views.panels.RenameFolderDialogPanel;
import com.extjs.gxt.ui.client.data.ModelData;
import com.extjs.gxt.ui.client.data.ModelIconProvider;
import com.extjs.gxt.ui.client.event.Events;
import com.extjs.gxt.ui.client.event.GridEvent;
import com.extjs.gxt.ui.client.event.Listener;
import com.extjs.gxt.ui.client.store.TreeStore;
import com.extjs.gxt.ui.client.widget.grid.ColumnConfig;
import com.extjs.gxt.ui.client.widget.grid.ColumnModel;
import com.extjs.gxt.ui.client.widget.treegrid.TreeGrid;
import com.extjs.gxt.ui.client.widget.treegrid.TreeGridCellRenderer;
import com.google.gwt.event.shared.HandlerRegistration;
import com.google.gwt.user.client.rpc.AsyncCallback;
import com.google.gwt.user.client.ui.AbstractImagePrototype;
/**
* Provides a grid representation of disk resources for user interaction.
*/
public class DataBrowserGrid extends TreeGrid<DiskResource>
{
/**
* When displaying all columns, an arbitrary column padding was included in the
* original implementation and is expected by parent widgets. This constant helps
* preserve the expected look and feel of the widget by consuming widgets.
*/
public static final int ARBITRARY_COLUMN_PADDING = 30;
private TreeStoreWrapper storeWrapper;
private ColumnDisplay columnDisplay;
private List<HandlerRegistration> handlers;
protected DataBrowserGrid(ColumnDisplay columnDisplay, TreeStoreWrapper storeWrapper,
TreeStore<DiskResource> store, ColumnModel colModel)
{
super(store, colModel);
addListener(Events.ViewReady, new Listener<GridEvent<DiskResource>>()
{
@Override
public void handleEvent(GridEvent<DiskResource> be)
{
expandRootFolder();
}
});
this.storeWrapper = storeWrapper;
this.columnDisplay = columnDisplay;
initEventHandlers();
disableBrowserContextMenu();
assembleView();
}
private static DataBrowserGrid createInstanceImpl(ColumnDisplay columnDisplay)
{
TreeStoreWrapper storeWrapper = new TreeStoreWrapper();
TreeStore<DiskResource> store = storeWrapper.getStore();
final ColumnModel colModel = buildColumnModel(columnDisplay);
return new DataBrowserGrid(columnDisplay, storeWrapper, store, colModel);
}
public static DataBrowserGrid createInstance()
{
return createInstanceImpl(ColumnDisplay.ALL);
}
public static DataBrowserGrid createInstance(ColumnDisplay columnDisplay)
{
return createInstanceImpl(columnDisplay);
}
/**
* Reconstructs and reconfigures the underlying tree grid.
*
* @return a newly constructed and configure instance of tree grid.
*/
public TreeGrid<DiskResource> assembleView()
{
getFilesInfo();
final ColumnModel columnModel = buildColumnModel(columnDisplay);
return buildTreeGrid(getTreeStore(), columnModel);
}
/**
* Constructs and configures the underlying tree grid implementation.
*
* @param store the tree store holding the disk resources to display
* @param columnModel the specification of the columns for the grid
* @return a properly configured instance of a tree grid
*/
private TreeGrid<DiskResource> buildTreeGrid(TreeStore<DiskResource> store,
final ColumnModel columnModel)
{
int totalColumnWidth = computeColumnWidth(columnModel);
setBorders(true);
setHeight(260);
setWidth(totalColumnWidth);
getView().setShowDirtyCells(false);
setTrackMouseOver(false);
getTreeView().setBufferEnabled(false);
getTreeView().setCacheSize(10000);
setIconProvider(new ModelIconProvider<DiskResource>()
{
@Override
public AbstractImagePrototype getIcon(DiskResource model)
{
if(model instanceof Folder)
{
return getNodeIcon(isExpanded(model));
}
else
{
return AbstractImagePrototype.create(Resources.ICONS.green());
}
}
});
return this;
}
/**
* Computes the width of the grid based on the widths specified in the column
* configuration
*
* @param columnModel the list of column configuration objects
* @return an integer representing necessary width of this widget
*/
private int computeColumnWidth(ColumnModel columnModel)
{
int totalWidth = 0;
for(ColumnConfig cc : columnModel.getColumns())
{
totalWidth += cc.getWidth();
}
// when displaying all columns, include padding
if(columnDisplay == ColumnDisplay.ALL)
{
totalWidth += ARBITRARY_COLUMN_PADDING;
}
return totalWidth;
}
/**
* Determine the correct node icon to display.
*
* @param isExpanded true if the node is expanded; otherwise false.
* @return a boolean representing the state of the node in a tree grid
*/
private AbstractImagePrototype getNodeIcon(boolean isExpanded)
{
return isExpanded ? getStyle().getNodeOpenIcon() : getStyle().getNodeCloseIcon();
}
/**
* Create the column model for the tree grid.
*
* @return an instance of ColumnModel representing the columns visible in a grid
*/
private static ColumnModel buildColumnModel(ColumnDisplay colDisplay)
{
ColumnConfig name = new ColumnConfig("name", I18N.DISPLAY.name(), 330);
ColumnConfig date = new ColumnConfig("type", I18N.DISPLAY.description(), 190);
name.setRenderer(new TreeGridCellRenderer<ModelData>());
List<ColumnConfig> columns = new ArrayList<ColumnConfig>();
// add columns that are members of ColumnDisplay.CONCISE, a logical grouping of
// columns
columns.addAll(Arrays.asList(name, date));
// if we want ALL, include the remaining columns
if(colDisplay == ColumnDisplay.ALL)
{
ColumnConfig size = new ColumnConfig("uploaded", I18N.DISPLAY.uploaded(), 150);
columns.add(size);
}
return new ColumnModel(columns);
}
/**
* Disable the context menu of the browser using native JavaScript.
*
* This disables the user's ability to right-click on this widget and get the
* browser's context menu
*/
private static native void disableBrowserContextMenu()
/*-{
$doc.oncontextmenu = function() { return false; };
}-*/;
/**
* Retrieve list of all uploaded files contains in the user's workspace
*/
private void getFilesInfo()
{
UserInfo uinfo = UserInfo.getInstance();
String idWorkspace = uinfo.getWorkspaceId();
FolderServices.getFiletree(idWorkspace, new AsyncCallback<String>()
{
@Override
public void onFailure(Throwable arg0)
{
ErrorHandler.post(I18N.ERROR.retrieveFiletreeFailed());
}
@Override
public void onSuccess(String result)
{
updateStore(result);
}
});
}
private void expandRootFolder()
{
Folder root = storeWrapper.getRootFolder();
if(root != null)
{
setExpanded(root, true);
}
}
private void updateStore(String jsonResult)
{
storeWrapper.updateWrapper(jsonResult, true);
expandRootFolder();
}
private void initEventHandlers()
{
handlers = new ArrayList<HandlerRegistration>();
EventBus eventbus = EventBus.getInstance();
// folder added
handlers.add(eventbus.addHandler(FolderCreatedEvent.TYPE, new FolderCreatedEventHandler()
{
@Override
public void onCreated(FolderCreatedEvent event)
{
storeWrapper.createFolder(event.getParentId(), event.getFolderId(), event.getName());
}
}));
// file uploaded
handlers.add(eventbus.addHandler(FileUploadedEvent.TYPE, new FileUploadedEventHandler()
{
@Override
public void onUploaded(FileUploadedEvent event)
{
storeWrapper.addFile(event.getParentId(), event.getFileInfo(), event.getDeleteIds());
}
}));
// file save as completed
handlers.add(eventbus.addHandler(FileSaveAsEvent.TYPE, new FileSaveAsEventHandler()
{
@Override
public void onSaved(FileSaveAsEvent event)
{
storeWrapper.addFile(event.getParentId(), event.getFileInfo(), null);
}
}));
// folder/file renamed
handlers.add(eventbus.addHandler(DiskResourceRenamedEvent.TYPE,
new DiskResourceRenamedEventHandler()
{
@Override
public void onFolderRenamed(DiskResourceRenamedEvent event)
{
storeWrapper.renameFolder(event.getId(), event.getName());
}
@Override
public void onFileRenamed(DiskResourceRenamedEvent event)
{
storeWrapper.renameFile(event.getId(), event.getName());
}
}));
// deletions
handlers.add(eventbus.addHandler(DiskResourceDeletedEvent.TYPE,
new DiskResourceDeletedEventHandler()
{
@Override
public void onDeleted(DiskResourceDeletedEvent event)
{
storeWrapper.delete(event.getFolders(), event.getFiles());
}
}));
// file moved
handlers.add(eventbus.addHandler(FileMovedEvent.TYPE, new FileMovedEventHandler()
{
@Override
public void onMoved(FileMovedEvent event)
{
storeWrapper.moveFile(event.getFolderId(), event.getFileId());
}
}));
}
/**
* Get a list of disk resources the user has selected
*
* @return a list of disk resources
*/
public List<DiskResource> getSelectedDiskResources()
{
return getSelectionModel().getSelectedItems();
}
/**
* Prompt the user for necessary input to create a folder.
*/
public void promptForFolderCreate()
{
IPlantDialog dlg = new IPlantDialog(I18N.DISPLAY.newFolder(), 320, new AddFolderDialogPanel(
getRootParentId()));
dlg.show();
}
/**
* Prompt the user for either file or folder renaming.
*/
public void promptForRename()
{
DiskResource selected = getSelectionModel().getSelectedItem();
if(selected != null)
{
IPlantDialog dlg = null;
if(selected instanceof Folder)
{
dlg = new IPlantDialog(I18N.DISPLAY.rename(), 320, new RenameFolderDialogPanel(selected
.getId(), selected.getName()));
}
else if(selected instanceof File)
{
dlg = new IPlantDialog(I18N.DISPLAY.rename(), 320, new RenameFileDialogPanel(selected
.getId(), selected.getName()));
}
// do we have a dialog to display
if(dlg != null)
{
dlg.show();
}
}
}
/**
* Get the upload parent based on the user's selection(s)
*
* @return a string representing the root parent ID
*/
public String getRootParentId()
{
String ret = storeWrapper.getRootFolderId(); // by default - let's return the
// upload folder's id
List<DiskResource> items = getSelectedDiskResources();
// do we only have one item selected
if(items.size() == 1)
{
DiskResource selected = items.get(0);
// if we have a file... let's return the parent's id
if(selected instanceof File)
{
File file = (File)selected;
Folder parent = (Folder)file.getParent();
ret = parent.getId();
}
else
{
ret = selected.getId();
}
}
return ret;
}
private void removeEventHandlers()
{
EventBus eventbus = EventBus.getInstance();
// unregister
for(HandlerRegistration reg : handlers)
{
eventbus.removeHandler(reg);
}
// clear our list
handlers.clear();
}
public void cleanup()
{
removeEventHandlers();
}
/**
* Describes the column data that will be displayed in the will
*
* How the widget treats the enum values:
* <dl>
* <dt>ALL</dt>
* <dd>Informs this widget to display all columns: name, type, & uploaded date.</dd>
* <dt>CONCISE</dt>
* <dd>Informs this widget to display only columns: name & type.</dd>
* </dl>
*
* @author lenards
*
*/
public enum ColumnDisplay
{
/**
* All columns will be displayed in the grid.
*/
ALL,
/**
* A small subset of columns will be displayed in the grid.
*/
CONCISE
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment