/******************************************************************************* * Copyright (c) 2014, 2015 Scott Clarke (scott@dawg6.com). * * This file is part of Dawg6's Demon Hunter DPS Calculator. * * Dawg6's Demon Hunter DPS Calculator 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. * * Dawg6's Demon Hunter DPS Calculator 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 com.dawg6.web.dhcalc.client; import java.util.Map; import java.util.TreeMap; import com.dawg6.d3api.shared.HeroProfile; import com.dawg6.d3api.shared.ItemInformation; import com.dawg6.d3api.shared.Realm; import com.dawg6.gwt.client.ApplicationPanel; import com.dawg6.gwt.client.ApplicationPanel.DialogBoxResultHandler; import com.dawg6.gwt.common.util.DefaultCallback; import com.dawg6.web.dhcalc.shared.calculator.Slot; import com.google.gwt.core.client.JavaScriptObject; import com.google.gwt.core.client.JsonUtils; import com.google.gwt.event.dom.client.ClickEvent; import com.google.gwt.event.dom.client.ClickHandler; import com.google.gwt.http.client.URL; import com.google.gwt.storage.client.Storage; import com.google.gwt.user.client.Window; import com.google.gwt.user.client.rpc.AsyncCallback; import com.google.gwt.user.client.ui.Anchor; import com.google.gwt.user.client.ui.Button; import com.google.gwt.user.client.ui.CaptionPanel; import com.google.gwt.user.client.ui.Composite; import com.google.gwt.user.client.ui.FlexTable; import com.google.gwt.user.client.ui.HorizontalPanel; import com.google.gwt.user.client.ui.Label; import com.google.gwt.user.client.ui.ListBox; import com.google.gwt.user.client.ui.TextBox; import com.google.gwt.user.client.ui.VerticalPanel; public class GearPanel extends Composite { private final Map<Slot, Anchor> labels = new TreeMap<Slot, Anchor>(); private final Map<Slot, ItemHolder> items = new TreeMap<Slot, ItemHolder>(); private final String SAVED_ITEMS = "SAVED_ITEMS"; private final ListBox savedItems; @SuppressWarnings("unchecked") public GearPanel() { HorizontalPanel panel = new HorizontalPanel(); initWidget(panel); VerticalPanel verticalPanel_1 = new VerticalPanel(); panel.add(verticalPanel_1); CaptionPanel captionPanel = new CaptionPanel("Current Items"); verticalPanel_1.add(captionPanel); FlexTable table = new FlexTable(); captionPanel.add(table); CaptionPanel cptnpnlNewPanel = new CaptionPanel("Saved Items"); panel.add(cptnpnlNewPanel); VerticalPanel verticalPanel = new VerticalPanel(); cptnpnlNewPanel.setContentWidget(verticalPanel); verticalPanel.setSize("5cm", "3cm"); savedItems = new ListBox(); verticalPanel.add(savedItems); savedItems.setVisibleItemCount(20); savedItems.setWidth("100%"); HorizontalPanel horizontalPanel = new HorizontalPanel(); horizontalPanel.setSpacing(5); verticalPanel.add(horizontalPanel); Button btnNewButton = new Button("New button"); btnNewButton.setText("Rename..."); horizontalPanel.add(btnNewButton); btnNewButton.addClickHandler(new ClickHandler() { @Override public void onClick(ClickEvent event) { renameItem(); } }); Button btnNewButton_1 = new Button("New button"); btnNewButton_1.setText("Delete"); horizontalPanel.add(btnNewButton_1); btnNewButton_1.addClickHandler(new ClickHandler() { @Override public void onClick(ClickEvent event) { deleteItem(); } }); int row = 0; for (Slot slot : Slot.values()) if (!slot.isCube()) { final Slot thisSlot = slot; Label label = new Label(slot.name()); label.addStyleName("boldText"); table.setWidget(row, 0, label); Anchor status = new Anchor("unloaded"); status.setTarget("_blank"); status.setHref("javascript:void(0);"); table.setWidget(row, 1, status); labels.put(slot, status); status.addClickHandler(new ClickHandler() { @Override public void onClick(ClickEvent event) { event.preventDefault(); clickItem(thisSlot); } }); Button saveButton = new Button("save"); table.setWidget(row, 2, saveButton); saveButton.addClickHandler(new ClickHandler() { @Override public void onClick(ClickEvent event) { saveSlot(thisSlot); } }); Button replaceButton = new Button("replace"); table.setWidget(row, 3, replaceButton); replaceButton.addClickHandler(new ClickHandler() { @Override public void onClick(ClickEvent event) { replaceSlot(thisSlot); } }); Button clearButton = new Button("clear"); table.setWidget(row, 4, clearButton); clearButton.addClickHandler(new ClickHandler() { @Override public void onClick(ClickEvent event) { clearSlot(thisSlot); } }); row++; } Storage storage = getStorage(); if (storage != null) { String data = storage.getItem(SAVED_ITEMS); JsoArray<Entry> list = null; if (data != null) { list = JsonUtils.safeEval(data); } else { list = (JsoArray<Entry>) JavaScriptObject.createArray(); } for (int i = 0; i < list.length(); i++) { Entry e = list.get(i); savedItems.addItem(e.getName(), e.getItem()); } } setVisible(false); } protected void clickItem(Slot slot) { ItemHolder item = items.get(slot); if (item != null) { Window.open( "json?realm=US&item=" + URL.encodeQueryString(item.tooltip), "_blank", ""); } } protected void clearSlot(Slot slot) { setItem(slot, null); } protected void deleteItem() { int i = savedItems.getSelectedIndex(); if (i >= 0) { String name = savedItems.getItemText(i); String item = savedItems.getValue(i); JsoArray<Entry> list = removeItem(getSavedItems(), name, item); saveItems(list); savedItems.removeItem(i); savedItems.setSelectedIndex(i - 1); } } private JsoArray<Entry> removeItem(JsoArray<Entry> list, String name, String item) { @SuppressWarnings("unchecked") JsoArray<Entry> copy = (JsoArray<Entry>) JavaScriptObject.createArray(); for (int n = 0; n < list.length(); n++) { Entry e = list.get(n); if (!name.equals(e.getName()) || !item.equals(e.getItem())) copy.push(e); } return copy; } protected void renameItem() { final int i = savedItems.getSelectedIndex(); if (i >= 0) { final String name = savedItems.getItemText(i); final String item = savedItems.getValue(i); final TextBox field = new TextBox(); field.setText(name); ApplicationPanel.showDialogBox("Rename Item", field, ApplicationPanel.OK | ApplicationPanel.CANCEL, new DialogBoxResultHandler() { @Override public void dialogBoxResult(int result) { if (result == ApplicationPanel.OK) { JsoArray<Entry> list = removeItem( getSavedItems(), name, item); Entry e = (Entry) JavaScriptObject .createObject(); e.setName(field.getText()); e.setItem(item); list.push(e); saveItems(list); savedItems.removeItem(i); savedItems.insertItem(e.getName(), item, i); savedItems.setSelectedIndex(i); } } }); } } protected void replaceSlot(final Slot slot) { int i = savedItems.getSelectedIndex(); if (i >= 0) { String value = savedItems.getValue(i); ItemHolder item = new ItemHolder(value); setItem(slot, item); } } protected void saveSlot(Slot slot) { ItemHolder item = items.get(slot); if (item != null) { item.getInfo(new DefaultCallback<ItemInformation>(){ @Override protected void doOnSuccess(ItemInformation result) { saveItem(result.name, result); }}); } } @SuppressWarnings("unchecked") private JsoArray<Entry> getSavedItems() { Storage storage = getStorage(); if (storage != null) { String data = storage.getItem(SAVED_ITEMS); JsoArray<Entry> list = null; if (data != null) { list = JsonUtils.safeEval(data); } else { list = (JsoArray<Entry>) JavaScriptObject.createArray(); } return list; } else { return (JsoArray<Entry>) JavaScriptObject.createArray(); } } private void saveItems(JsoArray<Entry> list) { Storage storage = getStorage(); if (storage != null) { storage.setItem(SAVED_ITEMS, list.stringify()); } } private void saveItem(String name, ItemInformation item) { Storage storage = getStorage(); if (storage != null) { Entry entry = (Entry) JavaScriptObject.createObject(); entry.setName(name); entry.setItem(item.tooltipParams); JsoArray<Entry> list = getSavedItems(); list.push(entry); saveItems(list); savedItems.addItem(name, item.tooltipParams); int i = savedItems.getItemCount(); savedItems.setSelectedIndex(i - 1); } } public void setHero(HeroProfile hero) { if ((hero != null) && (hero.items != null)) { for (Slot slot : Slot.values()) if (!slot.isCube()) { ItemInformation item = hero.items.get(slot.getSlot()); if (item != null) setItem(slot, new ItemHolder(item)); else setItem(slot, null); } } } private void setItem(Slot slot, final ItemHolder item) { final Anchor label = labels.get(slot); String text = "unloaded"; String url = "javascript:void(0);"; if (item != null) { items.put(slot, item); url = "http://us.battle.net/d3/en/itemData/" + item.getTooltip(); if (this.isVisible()) { item.getInfo(new DefaultCallback<ItemInformation>(){ @Override protected void doOnSuccess(ItemInformation result) { label.setText(result.name); } }); } } else { items.remove(slot); label.setText(text); } label.setHref(url); } public void updateLabels() { for (Slot s : Slot.values()) if (!s.isCube()) { final Anchor label = labels.get(s); ItemHolder item = items.get(s); if (item != null) { String url = "http://us.battle.net/d3/en/itemData/" + item.getTooltip(); label.setHref(url); item.getInfo(new DefaultCallback<ItemInformation>(){ @Override protected void doOnSuccess(ItemInformation result) { label.setText(result.name); } }); } else { label.setHref("javascript:void(0)"); label.setText("Empty"); } } } private static class Entry extends JavaScriptObject { protected Entry() { } public final native String getName() /*-{ return this.name; }-*/; public final native String getItem() /*-{ return this.item; }-*/; public final native void setName(String iName) /*-{ this.name = iName; }-*/; public final native void setItem(String iItem) /*-{ this.item = iItem; }-*/; } private static class JsoArray<T extends JavaScriptObject> extends JavaScriptObject { protected JsoArray() { } public final native int length() /*-{ return this.length; }-*/; public final native T get(int i) /*-{ return this[i]; }-*/; public final native void push(T item) /*-{ this.push(item); }-*/; public final native String stringify() /*-{ return JSON.stringify(this); }-*/; } private Storage getStorage() { Storage s = Storage.getLocalStorageIfSupported(); if (s == null) { ApplicationPanel .showErrorDialog("Local Storage not supported by your browser"); } return s; } public Map<Slot, ItemHolder> getItems() { return new TreeMap<Slot, ItemHolder>(items); } public void populateFormData(Map<String, String> data) { Map<Slot, ItemHolder> items = getItems(); data.clear(); for (Slot s : Slot.values()) if (!s.isCube()) { ItemHolder item = items.get(s); if ((item != null) && (item.getTooltip() != null)) { data.put(s.getSlot(), item.getTooltip()); } } } public void restoreData(Map<String, String> items) { for (Slot s : Slot.values()) if (!s.isCube()) { final Slot slot = s; String item = items.get(s.getSlot()); if (item != null) { setItem(slot, new ItemHolder(item)); } else { setItem(slot, null); } } } public void clearData() { for (Slot s : Slot.values()) if (!s.isCube()) setItem(s, null); } public static class ItemHolder { private final String tooltip; private ItemInformation info; public ItemHolder(String tooltip) { this.tooltip = tooltip; this.info = null; } public ItemHolder(ItemInformation info) { this.tooltip = info.tooltipParams; this.info = info; } public String getTooltip() { return tooltip; } public void getInfo(AsyncCallback<ItemInformation> callback) { if (info == null) { Service.getInstance().getItem(Realm.US, tooltip, new DefaultCallback<ItemInformation>(callback) { @Override protected void doOnSuccess(ItemInformation result) { info = result; } }); } else { callback.onSuccess(info); } } } }