PDA

View Full Version : More questions about web app similar to AdvancedListView demo



SuperSloMo
17 Dec 2010, 10:12 PM
I am putting together a web application that is very similar to the AdvancedListView demo, and I am stuck on three things.

1. When I bring my webpage up, a window is supposed to display thumbnails in a window like the Dialog object that is assigned to the variable called chooser in the demo. In my application, that window first appears as a tool bar with no window below it until I resize that window, and then all of the thumbnails appear. For that part of my application I literally copied the code used in the demo for setting up the chooser, main and details objects, although I have since changed the chooser from a Dialog object to a Window object because I don't need buttons on it. I have looked over my code and the source code of the AdvancedListView demo several times to see if I have overlooked some crucial function call that is needed to make the thumbnails appear in the main content panel as soon as they are loaded into that panel's ListView's store, but so far I haven't figured out what I need to do to fix this problem. Before I put the main content panel into the chooser I was playing around with a version of the app where the main content panel was the only thing in the web page, and then I could only get the thumbnails to display by changing the size of the browser window, so it's clear that some kind of event has to happen to make the content panel display its contents. I don't know how to tell which event it is or how to change things so that that event is not required.

2. The thumbnails are displayed in the main content panel in rows and columns according to the panel's size, and when I move the mouse over the images, it rearranges the thumbnails in the rows below it. I think this is a stylesheet issue, because until I copied the stylesheet entries used in the AdvancedListView demo into the .css file for my application, the thumbnails were displayed in one vertical column at the left edge of the main content panel. The stylesheet entries allow the thumbnails to be rearranged to fit into the main panel better, but putting the mouse over a thumbnail causes all of the positions in the row below it that are to the left of that thumbnail to be cleared out, and everything is shifted by the number of positions that are cleared. So if I have 12 thumbnails that are arranged like this:
X X X X
X X X X
X X X X
and I move the mouse over the third thumbnail in the second row, they become arranged like this:
X X X X
X X M X
X X
X X
Moving the mouse from thumbnail to thumbnail causes them to rearrange themselves over and over again, usually leaving a gap in the row below where the mouse is. I have not debugged CSS issues before, so any advice on how to go about it would be appreciated.

3. I changed the ListView used in the AdvancedListView to be a CheckBoxListView in my application. This is to allow the user to select one or more images and download them to a directory that they choose. I don't know how to display a download dialog box in GXT, and non-GXT examples that I have seen on the internet all show how to download a single file. I tried the methods that I found with a single selected image, and I couldn't get them to work. Are there GWT or GXT classes that support file download? If so, can they be adapted to support downloading several files to the same destination in one step? If not, what other solutions are there for downloading files from a web app to the user's computer? Thanks.

SuperSloMo
17 Dec 2010, 10:15 PM
Oops, the second diagram of thumbnails is incorrect. It should look like this:


X X X X
X X M X
X X
X X

sven
18 Dec 2010, 3:40 AM
1) This sounds like a issue in your layoutchain. You will need to post a fully working testcase implementing EntryPoint.

2) Set a white border around each listview item. That should fix this.

3) You need to make a request to your server and request the download archieve there. No way to create an archieve client side

SuperSloMo
18 Dec 2010, 3:23 PM
Here is the source code that I am working on. I hope you can wade through the convoluted parts to get at the parts that have to do with updating and displaying the images. Thanks.
Mike


public class NISTImageBrowser implements EntryPoint {

private enum Subdir {
METADATA,
ORIGINAL,
STANDARD,
THUMBNAIL,
WEBDISPLAY
}

// This is the nistImagesRootPath to use for a deployed web service.
private static final String nistImagesRootPath = "/addama/repositories/nistimagerepo";

private HashMap<Subdir, String> subdirUrlMap;

private HashMap<String, NISTImage> standardImageURLMap;
private HashMap<String, NISTImage> thumbnailImageURLMap;
private HashMap<String, NISTImage> webdisplayImageURLMap;

private Window chooser;
private LayoutContainer details;
private XTemplate detailTp;
private Image image;
private Text infoPane;
private ContentPanel main;
private ListStore<BeanModel> store;
private CheckBoxListView<BeanModel> view;
private Viewport viewport;

/**
* This is the entry point method.
*/
public void onModuleLoad() {

subdirUrlMap = new HashMap<Subdir, String>();

metadataImageURLMap = new HashMap<String, String>();
standardImageURLMap = new HashMap<String, NISTImage>();
thumbnailImageURLMap = new HashMap<String, NISTImage>();
webdisplayImageURLMap = new HashMap<String, NISTImage>();

viewport = new Viewport();
viewport.setLayout(new VBoxLayout());

main = new ContentPanel();
main.setBorders(true);
main.setBodyBorder(false);
main.setLayout(new FitLayout());
main.setHeaderVisible(false);
main.setHeight(600);
main.setWidth(1500);

ToolBar bar = new ToolBar();
bar.add(new Button("Download Images", new SelectionListener<ButtonEvent>() {
@Override
public void componentSelected(ButtonEvent ce) {
List<BeanModel> checkedFiles = view.getChecked();

for (BeanModel file : checkedFiles) {
String link = file.get("uri");
viewport.add(new HTML("<a href=\"" + link + "\">Download File</a>"));
}
}}));
main.setTopComponent(bar);

GetSubdirContents getThumbnails = new GetSubdirContents(Subdir.THUMBNAIL, thumbnailImageURLMap);
getThumbnails.setResponseAction(new PopulateThumbnailListView());
getThumbnails.submitRequest();

details = new LayoutContainer();

details.setBorders(true);
details.setStyleAttribute("backgroundColor", "white");

image = new Image();
image.getElement().getStyle().setProperty("marginTop", "10px");
image.setVisible(false);
details.add(image);

detailTp = XTemplate.create(getDetailTemplate());

chooser = new Window();
chooser.setId("img-chooser-dlg");
chooser.setHeading("Choose an Image");
chooser.setMinWidth(1000);
chooser.setMinHeight(600);
chooser.setModal(true);
chooser.setLayout(new BorderLayout());
chooser.setBodyStyle("border: none;background: none");
chooser.setBodyBorder(false);
chooser.setClosable(false);

BorderLayoutData eastData = new BorderLayoutData(LayoutRegion.EAST, 150, 150, 250);
eastData.setSplit(true);

BorderLayoutData centerData = new BorderLayoutData(LayoutRegion.CENTER);
centerData.setMargins(new Margins(0, 5, 0, 0));

chooser.add(main, centerData);
chooser.add(details, eastData);

viewport.add(chooser);

// TODO: Find place for infoPane to be displayed
infoPane = new Text();
infoPane.setStyleAttribute("float", "left");
infoPane.setSize(500, 40);
infoPane.setBorders(false);

RootPanel.get().add(viewport);
}

private void onSelectionChange(SelectionChangedEvent<BeanModel> se) {
if (se.getSelection().size() > 0) {
BeanModel selectedBean = se.getSelection().get(0);
GetSubdirContents getWebDisplayImages = new GetSubdirContents(Subdir.WEBDISPLAY, webdisplayImageURLMap);
getWebDisplayImages.setResponseAction(new ShowWebDisplayImage(selectedBean.get("name").toString()));
getWebDisplayImages.submitRequest();
} else {
details.el().setInnerHtml("");
}
}

interface ResponseAction {
public void doResponseAction();
}

class PopulateThumbnailListView implements ResponseAction {
public void doResponseAction() {
List<NISTImage> tempList = new ArrayList<NISTImage>(thumbnailImageURLMap.values());
MemoryProxy<List<Image>> proxy = new MemoryProxy<List<Image>>(tempList);
ListLoader<ListLoadResult<Image>> loader =
new BaseListLoader<ListLoadResult<Image>>(proxy, new BeanModelReader());
store = new ListStore<BeanModel>(loader);
loader.load();
view = new CheckBoxListView<BeanModel>();
main.add(view);
view.setId("img-chooser-view");
view.setTemplate(getTemplate());
view.setBorders(false);
view.setStore(store);
view.setItemSelector("div.thumb-wrap");
view.getSelectionModel().setSelectionMode(SelectionMode.SINGLE);
view.getSelectionModel().addListener(Events.SelectionChange,
new Listener<SelectionChangedEvent<BeanModel>>() {
public void handleEvent(SelectionChangedEvent<BeanModel> be) {
onSelectionChange(be);
}});
}
}

class ShowWebDisplayImage implements ResponseAction {
private String imageName;

public ShowWebDisplayImage(String imageName) {
this.imageName = imageName;
}

public void doResponseAction() {
if (webdisplayImageURLMap.containsKey(imageName)) {
NISTImage selectedImage = webdisplayImageURLMap.get(imageName);
image.setUrl(selectedImage.getUri());
image.setVisible(true);
ModelData bean = new BaseModelData(selectedImage.getDataMap());

detailTp.overwrite(details.getElement(), Util.getJsObject(bean));
}
}
}

abstract class RepositoryAction {
abstract protected void doAction(String response);
abstract protected void submitRequest();
abstract protected String getUri();

protected void submitNISTImagesRequest(final RepositoryAction action) {
RequestBuilder builder = new RequestBuilder(RequestBuilder.GET, URL.encode(getUri()));

try {
builder.sendRequest(null, new RequestCallback() {
public void onError(Request request, Throwable exception) {
infoPane.setText("The following error occurred when sending the request " +
request.toString() + " to the NISTImages web service:\n" +
exception.getMessage());
}
public void onResponseReceived(Request request, Response response) {
int statusCode = response.getStatusCode();

if (200 == statusCode) {
String returnString = response.getText();

action.doAction(returnString);
} else {
infoPane.setText("Submitting the request " + request.toString() +
" to the NISTImages web service returned the status code " + statusCode);
}}});
} catch (RequestException reExcept) {
infoPane.setText("The following error occurred when sending a request to the NISTImages web service:\n" +
reExcept.getMessage());
} catch (Exception ex) {
infoPane.setText("The following error occurred when sending a request to the NISTImages web service:\n" +
ex.getMessage());
}
}
}

class GetSubdirUrls extends RepositoryAction {
private GetSubdirContents action;

public GetSubdirUrls(GetSubdirContents action) {
this.action = action;
}

public String getUri() {
return nistImagesRootPath;
}

public void submitRequest() {
submitNISTImagesRequest(this);
}

public void doAction(String responseString) {
try {
JSONValue subdirs = JSONParser.parseLenient(responseString);
JSONObject subdirsObject = subdirs.isObject();
JSONArray subdirsArray = (JSONArray)subdirsObject.get("items");

for (int i = 0; i < subdirsArray.size(); i++) {
JSONObject subdirObj = subdirsArray.get(i).isObject();
String subdirName = subdirObj.get("name").isString().stringValue();
String subdirUri = subdirObj.get("uri").isString().stringValue();

if (subdirName.equals("Original")) {
subdirUrlMap.put(Subdir.ORIGINAL, subdirUri);
} else if (subdirName.equals("Standard")) {
subdirUrlMap.put(Subdir.STANDARD, subdirUri);
} else if (subdirName.equals("Thumbnail")) {
subdirUrlMap.put(Subdir.THUMBNAIL, subdirUri);
} else if (subdirName.equals("WebDisplay")) {
subdirUrlMap.put(Subdir.WEBDISPLAY, subdirUri);
}
}
} catch (NullPointerException ex_np) {
infoPane.setText("The following error occurred when updating the list of repository subdirectories:\n" +
ex_np.getMessage());
} catch (IllegalArgumentException ex_ia) {
infoPane.setText("The following error occurred when updating the list of repository subdirectories:\n" +
ex_ia.getMessage());
}
if (action != null) {
action.submitRequest();
}
}
}

class GetSubdirContents extends RepositoryAction {
private HashMap<String, NISTImage> contentsMap;
private ResponseAction responseAction = null;
private Subdir subdir;


public GetSubdirContents(Subdir subdir, HashMap<String, NISTImage> imageMap) {
this.contentsMap = imageMap;
this.subdir = subdir;
}

public HashMap<String, NISTImage> getImageMap() {
return contentsMap;
}

public Subdir getSubdir() {
return subdir;
}

public String getUri() {
String uri;

if (subdirUrlMap.isEmpty() || !subdirUrlMap.containsKey(subdir)) {
uri = null;
} else {
uri = subdirUrlMap.get(subdir);
}
return uri;
}

public void setResponseAction(ResponseAction action) {
responseAction = action;
}

public ResponseAction getResponseActions() {
return responseAction;
}

public void submitRequest() {
if (subdirUrlMap.isEmpty()) {
RepositoryAction getSubdirs = new GetSubdirUrls(this);
getSubdirs.submitRequest();
} else {
submitNISTImagesRequest(this);
}
}

public void doAction(String responseString) {
if (subdirUrlMap.isEmpty()) {
submitNISTImagesRequest(new GetSubdirUrls(this));
} else {
try {
JSONValue images = JSONParser.parseLenient(responseString);
JSONObject imagesObject = images.isObject();
JSONArray imagesArray = (JSONArray)imagesObject.get("items");

for (int i = 0; i < imagesArray.size(); i++) {
JSONObject imageObj = imagesArray.get(i).isObject();
String imageName = imageObj.get("name").isString().stringValue();
String imageUri = imageObj.get("uri").isString().stringValue();
String imageLocalUri = imageObj.get("local").isString().stringValue();
boolean imageIsFile = imageObj.get("isFile").isBoolean().booleanValue();

if (imageIsFile) {
NISTImage image = new NISTImage();
String imageLookupName = NISTImageBrowserUtils.removeExtension(imageName);

image.setDate(new Date()); // TODO: Get actual date
image.setFile(NISTImageBrowserUtils.makeFilePathname(imageUri));
image.setName(imageLookupName);
image.setLocalUri(imageLocalUri);
image.setSize(1000); // TODO: get actual size
image.setUri(imageUri);

contentsMap.put(imageLookupName, image);
}
}
if (responseAction != null) {
responseAction.doResponseAction();
}
} catch (NullPointerException ex_np) {
infoPane.setText("The following error occurred when updating the list of images:\n" +
ex_np.getMessage());
} catch (IllegalArgumentException ex_ia) {
infoPane.setText("The following error occurred when updating the list of images:\n" +
ex_ia.getMessage());
}
}
}
}

private native String getTemplate() /*-{
return ['<tpl for=".">',
'<div class="thumb-wrap" id="{name}">',
'<div class="thumb"><input class="x-view-item-checkbox" type="checkbox" id="{file}" /><img src="{file}" title="{name}"></div>',
'<span class="x-editable">{name}</span></div>',
'</tpl>',
'<div class="x-clear"></div>'].join("");

}-*/;

public native String getDetailTemplate() /*-{
return ['<div class="details">',
'<tpl for=".">',
'<img src="{file}"><div class="details-info">',
'<b>Image Name:</b>',
'<span>{name}</span>',
'<b>Size:</b>',
'<span>{size}</span>',
'<b>Last Modified:</b>',
'<span>{date}</span></div>',
'</tpl>',
'</div>'].join("");
}-*/;
}

SuperSloMo
19 Dec 2010, 4:11 PM
1) This sounds like a issue in your layoutchain. You will need to post a fully working testcase implementing EntryPoint.

2) Set a white border around each listview item. That should fix this.

3) You need to make a request to your server and request the download archieve there. No way to create an archieve client side

Could you explain to me how to do 2)? I have tried a few ways to put white borders around the listview items, but I haven't found one that works yet. Thanks.

SuperSloMo
19 Dec 2010, 6:25 PM
Could you explain to me how to do 2)? I have tried a few ways to put white borders around the listview items, but I haven't found one that works yet. Thanks.

Never mind about 2), I figured out how to do it. I am still stumped about why my thumbnails in my CheckBoxListView don't appear in the window until I resize it though. Thanks.

SuperSloMo
20 Dec 2010, 7:40 PM
I worked out a way to get the images to display in the window by calling setHeight and setWidth on the Window object assigned to chooser (I had thought that calling setMinHeight and setMinWidth was sufficient) and also constructing the ListStore like this:


store = new ListStore<BeanModel>(loader) {
@Override
protected void onLoad(LoadEvent le) {
super.onLoad(le);
main.layout();
}
};

main is the ContentPanel that contains the CheckBoxListView inside the Window object. Is this the best way to get this working, or is there a better one? Thanks.