Java tutorial
/* * License information at https://github.com/Caltech-IPAC/firefly/blob/master/License.txt */ package edu.caltech.ipac.firefly.ui; import com.google.gwt.event.dom.client.KeyCodes; import com.google.gwt.event.dom.client.KeyDownEvent; import com.google.gwt.event.dom.client.KeyDownHandler; import com.google.gwt.event.logical.shared.ValueChangeEvent; import com.google.gwt.event.logical.shared.ValueChangeHandler; import com.google.gwt.i18n.client.NumberFormat; import com.google.gwt.user.client.Command; import com.google.gwt.user.client.DeferredCommand; import com.google.gwt.user.client.Timer; import com.google.gwt.user.client.rpc.AsyncCallback; import com.google.gwt.user.client.ui.Composite; import com.google.gwt.user.client.ui.HTML; import com.google.gwt.user.client.ui.HorizontalPanel; import com.google.gwt.user.client.ui.SimplePanel; import com.google.gwt.user.client.ui.VerticalPanel; import com.google.gwt.user.client.ui.Widget; import edu.caltech.ipac.firefly.core.Preferences; import edu.caltech.ipac.firefly.data.Param; import edu.caltech.ipac.firefly.data.ServerParams; import edu.caltech.ipac.firefly.data.form.PositionFieldDef; import edu.caltech.ipac.firefly.rpc.TargetServices; import edu.caltech.ipac.firefly.ui.input.AsyncInputFieldGroup; import edu.caltech.ipac.firefly.ui.input.InputField; import edu.caltech.ipac.firefly.ui.input.SimpleInputField; import edu.caltech.ipac.firefly.visualize.ActiveTarget; import edu.caltech.ipac.firefly.visualize.VisUtil; import edu.caltech.ipac.astro.net.Resolver; import edu.caltech.ipac.util.ComparisonUtil; import edu.caltech.ipac.util.StringUtils; import edu.caltech.ipac.util.dd.EnumFieldDef; import edu.caltech.ipac.util.dd.ValidationException; import edu.caltech.ipac.visualize.plot.CoordinateSys; import edu.caltech.ipac.visualize.plot.ResolvedWorldPt; import edu.caltech.ipac.visualize.plot.WorldPt; import java.util.ArrayList; import java.util.Arrays; import java.util.Iterator; import java.util.List; import static edu.caltech.ipac.firefly.util.PositionParser.Input.Name; import static edu.caltech.ipac.firefly.util.PositionParser.Input.Position; /** * Created by IntelliJ IDEA. * User: tlau * Date: Nov 25, 2010 * Time: 5:35:55 PM * To change this template use File | Settings | File Templates. */ public class SimpleTargetPanel extends Composite implements AsyncInputFieldGroup { public static final String TARGET_NAME_KEY = "TargetPanel.field.targetName"; public static final String RESOLVED_BY_KEY = "SimpleTargetPanel.field.resolvedBy"; public static final String POSITION_KEY = "SimpleTargetPanel.field.position"; public static final String RESOLVE_BY_PREF = "TargetResolver"; private static final NumberFormat nf = NumberFormat.getFormat("#.######"); private enum ResolveAction { None, Resolving, Failed } private VerticalPanel mainPanel; private PositionFieldDef posFd; private InputField posField; private InputField resolveByField; private boolean ignoreValidation; private SimplePanel feedback = new SimplePanel(); private ResolveTimer resolveTimer = new ResolveTimer(); private Widget helpWidget; private ResolveTask _activeTask; private String _lastInput = ""; private List<Resolver> _supportedResolvers = new ArrayList<Resolver>(6); // public SimpleTargetPanel() { this("NED", "Simbad", "ptf"); } public SimpleTargetPanel() { this("nedthensimbad", "SimbadthenNED"); } public SimpleTargetPanel(String... resolvers) { init(resolvers); initWidget(mainPanel); } //==================================================================== // convenience unvalidated getter/setter //==================================================================== public String getTargetName() { String v = posFd.getObjectName(); if (v == null) v = ""; return v; } public InputField getInputField() { return posField; } public void setTargetName(String name) { setTarget(name, null, getResolver()); } public Resolver getResolver() { return parseResolver(resolveByField.getValue()); } public Resolver parseResolver(String resolveStr) { Resolver retval = Resolver.parse(resolveStr); if (!_supportedResolvers.contains(retval)) retval = Resolver.NONE; if (!retval.equals(Resolver.NONE)) { Preferences.set(RESOLVE_BY_PREF, resolveStr); ((EnumFieldDef) resolveByField.getFieldDef()).setDefaultValue(resolveStr); } return retval; } public void setResolver(Resolver resolver) { if (resolver != null && _supportedResolvers.contains(resolver)) { resolveByField.setValue(resolver.getKey()); } else { resolveByField.setValue(_supportedResolvers.get(0).getKey()); } updateFeedback(); } public ResolvedWorldPt getPos() { ResolvedWorldPt pos; if (posFd.getInputType() == Position) { WorldPt fdPos = posFd.getPosition(); pos = ResolvedWorldPt.makePt(fdPos); } else if (ResolverCache.isCached(posFd.getObjectName(), getResolver())) { pos = ResolverCache.get(posFd.getObjectName(), getResolver()); } else { pos = null; } return pos; } public WorldPt getJ2000Pos() { WorldPt pos = getPos(); WorldPt retval = pos; if (pos != null && !pos.getCoordSys().equals(CoordinateSys.EQ_J2000)) { retval = VisUtil.convert(pos, CoordinateSys.EQ_J2000); } return retval; } public List<Param> getFieldValues() { List<Param> list = new ArrayList<Param>(3); WorldPt wp = getPos(); if (wp != null) { list.add(new Param(ServerParams.USER_TARGET_WORLD_PT, new WorldPt(wp).toString())); } if (posFd.getInputType() == Name) { list.add(new Param(TARGET_NAME_KEY, posFd.getObjectName())); } list.add(new Param(RESOLVED_BY_KEY, getResolver().toString())); return list; } public void setFieldValues(List<Param> list) { String posName = null; WorldPt wp = null; Resolver resolver = Resolver.NED; for (Param p : list) { if (p.getName().equals(ServerParams.USER_TARGET_WORLD_PT)) { wp = WorldPt.parse(p.getValue()); } else if (p.getName().equals(TARGET_NAME_KEY)) { posName = p.getValue(); } else if (p.getName().equals(RESOLVED_BY_KEY)) { resolver = Resolver.parse(p.getValue()); } } setTarget(posName, wp, resolver); updateFeedback(); } public void getFieldValuesAsync(final AsyncCallback<List<Param>> cb) { if (isAsyncCallRequired() && isResolveNeeded()) { resolveTargetName(true, new AsyncCallback<ResolvedWorldPt>() { public void onFailure(Throwable caught) { cb.onFailure(caught); } public void onSuccess(ResolvedWorldPt wpt) { cb.onSuccess(getFieldValues()); } }); } else { cb.onSuccess(getFieldValues()); } } public boolean isAsyncCallRequired() { return isResolveNeeded(); } public ActiveTarget.PosEntry getTarget() { String tname = getTargetName(); tname = StringUtils.isEmpty(tname) ? null : tname; return new ActiveTarget.PosEntry(getPos(), tname, getResolver(), false); } public void setTarget(ActiveTarget.PosEntry target) { if (target != null) { setTarget(target.getName(), target.getPt(), target.getResolver(), target.isComputed()); } } private void setTarget(String name, WorldPt wp, Resolver resolver) { setTarget(name, wp, resolver, false); } private void setTarget(String name, WorldPt wp, Resolver resolver, boolean computed) { if (wp == null && !StringUtils.isEmpty(name)) { posField.setValue(name); setTarget(null, false); triggerResolverWithWait(); } else { setTarget(ResolvedWorldPt.makePt(wp, name, resolver), computed); } } private void setTarget(ResolvedWorldPt wp, boolean computed) { if (wp != null) { if (!StringUtils.isEmpty(wp.getObjName())) { posField.setValue(wp.getObjName()); } else { posField.setValue(PositionFieldDef.formatPosForTextField(wp)); } } Resolver resolver = (wp != null) ? wp.getResolver() : null; setResolver(resolver); if (wp != null && !computed && resolver != null && resolver != Resolver.NONE && !StringUtils.isEmpty(wp.getObjName())) { ResolverCache.put(wp); } updateActive(); updateFeedback(); } public void setIgnoreValidation(boolean ignoreValidation) { this.ignoreValidation = ignoreValidation; } public boolean validate() { if (ignoreValidation) { return true; } boolean retval = posField.validate() && GwtUtil.validateBlank(posField); if (retval) updateActive(); return retval; } private void updateActive() { String tname = getTargetName(); tname = StringUtils.isEmpty(tname) ? null : tname; ActiveTarget.getInstance().setActive(tname, getPos(), getResolver(), false); } //==================================================================== // //==================================================================== public void setBorder(boolean border) { if (border) mainPanel.setBorderWidth(1); else mainPanel.setBorderWidth(0); } private void init(String resolvers[]) { helpWidget = getHelp(); SimpleInputField posWrap = SimpleInputField.createByProp(POSITION_KEY); posField = posWrap.getField(); posFd = (PositionFieldDef) posField.getFieldDef(); Resolver r; for (String rStr : resolvers) { r = Resolver.parse(rStr); if (r != Resolver.NONE) _supportedResolvers.add(r); } if (_supportedResolvers.size() == 0) { _supportedResolvers.add(Resolver.NED); _supportedResolvers.add(Resolver.Simbad); } resolveByField = createResolverField(_supportedResolvers); // resolveByField = FormBuilder.createField(RESOLVED_BY_KEY); String resolveByPref = Preferences.get(RESOLVE_BY_PREF); if (!StringUtils.isEmpty(resolveByPref)) { Resolver def = parseResolver(resolveByPref); if (def != Resolver.NONE) setResolver(def); } addChangeListeners(); feedback.setSize("400px", "3em"); // feedback.setWidth("400px"); GwtUtil.setStyle(resolveByField, "marginTop", "6px "); HorizontalPanel top = new HorizontalPanel(); top.add(posWrap); top.add(resolveByField); top.setSpacing(1); mainPanel = new VerticalPanel(); mainPanel.add(top); mainPanel.add(feedback); mainPanel.setCellVerticalAlignment(top, VerticalPanel.ALIGN_MIDDLE); mainPanel.setCellVerticalAlignment(feedback, VerticalPanel.ALIGN_TOP); updateFeedback(); } private InputField createResolverField(List<Resolver> resolvers) { EnumFieldDef fd = new EnumFieldDef(RESOLVED_BY_KEY); fd.setShortDesc("Select resolver to retrieve coordinates"); fd.setPreferWidth(125); boolean first = true; for (Resolver resolver : resolvers) { if (resolver != Resolver.NONE) { fd.addItem(resolver.getKey(), resolver.getUserDesc()); if (first) fd.setDefaultValue(resolver.getKey()); first = false; } } return FormBuilder.createField(fd); } //==================================================================== // implementing HasWidget //==================================================================== public void add(Widget w) { throw new UnsupportedOperationException("This operation is not allowed"); } public void clear() { throw new UnsupportedOperationException("This operation is not allowed"); } public Iterator<Widget> iterator() { return new ArrayList<Widget>(Arrays.asList(posField, resolveByField)).iterator(); } public boolean remove(Widget w) { throw new UnsupportedOperationException("This operation is not allowed"); } //==================================================================== // private methods //==================================================================== private void addChangeListeners() { KeyDownHandler posQueryKph = new KeyDownHandler() { public void onKeyDown(KeyDownEvent ev) { int c = ev.getNativeKeyCode(); if (c == KeyCodes.KEY_TAB || c == KeyCodes.KEY_ENTER) { updateAsync(true); } else { updateAsync(false); } } }; ValueChangeHandler<String> tgtChangeHan = new ValueChangeHandler<String>() { public void onValueChange(ValueChangeEvent<String> ev) { updateAsync(true); } }; posField.getFocusWidget().addKeyDownHandler(posQueryKph); resolveByField.addValueChangeHandler(tgtChangeHan); // posField.addValueChangeHandler(tgtChangeHan); } private void triggerResolverWithWait() { if (ResolverCache.isCached(getTargetName(), getResolver())) { triggerResolver(false); } else { resolveTimer.cancel(); resolveTimer.restart(); } } private void triggerResolver(boolean mask) { resolveTimer.cancel(); if (posFd.getInputType() == Name) { String name = posFd.getObjectName(); if (_activeTask == null) { resolveTargetName(mask, null); } else if (!ComparisonUtil.equals(_activeTask.getName(), name)) { cancelResolverTask(); resolveTargetName(mask, null); } else { // do nothing correct resolve in progress } } else { cancelResolverTask(); } } private boolean isResolveNeeded() { String name = getTargetName(); Resolver resolver = getResolver(); return (!StringUtils.isEmpty(name) && resolver != Resolver.NONE && !ResolverCache.isCached(name, resolver)); } private void resolveTargetName(boolean mask, final AsyncCallback<ResolvedWorldPt> callback) { String name = getTargetName(); if (!StringUtils.isEmpty(name)) { Resolver resolver = getResolver(); if (isResolveNeeded()) { if (ResolverCache.isCached(name, resolver)) { ResolvedWorldPt wp = ResolverCache.get(name, resolver); resolveSuccess(name, wp, callback); } else { if (_activeTask != null) _activeTask.cancel(); _activeTask = new ResolveTask(name, resolver, callback); _activeTask.setAutoMask(mask); _activeTask.start(); } } else { updateFeedback(); } } } private void resolveSuccess(String name, final ResolvedWorldPt pos, final AsyncCallback<ResolvedWorldPt> callback) { if (name.equals(getTargetName())) { updateActive(); updateFeedback(); if (callback != null) { DeferredCommand.addCommand(new Command() { public void execute() { callback.onSuccess(pos); } }); } } } private void cancelResolverTask() { if (_activeTask != null) _activeTask.cancel(); } private void updateAsync(final boolean resolveNow) { if (_activeTask != null) _activeTask.cancel(); DeferredCommand.addCommand(new Command() { public void execute() { updateFeedback(); if (posFd.getInputType() == Name) { if (resolveNow) { triggerResolver(true); } else { triggerResolverWithWait(); } } } }); } private void updateFeedback() { updateFeedback(ResolveAction.None); } private void updateFeedback(ResolveAction resAction) { String s = null; String val = posField.getValue(); String wrapBegin = "<div style=\"text-align: center; line-height: 1;\">"; String wrapEnd = "</div>"; try { if (!StringUtils.isEmpty(val) && posFd.validate(val)) { if (posFd.getInputType() == Position) { WorldPt pt = posFd.getPosition(); if (pt != null) s = PositionFieldDef.formatPosForHelp(pt); } else { String name = posFd.getObjectName(); ResolvedWorldPt resolvedPos = ResolverCache.get(name, getResolver()); if (resAction == ResolveAction.Failed) { s = bold(name) + ": Could not resolve position using " + getResolver().getUserDesc(); } else if (resAction == ResolveAction.Resolving) { s = bold(name) + " <i>resolving now using</i> " + getResolver().getUserDesc(); } else if (resolvedPos != null) { s = PositionFieldDef.formatTargetForHelp(resolvedPos); } else { s = "Target Name: " + bold(name); } } } else { s = null; } } catch (ValidationException e) { s = null; } if (s != null) feedback.setWidget(new HTML(wrapBegin + s + wrapEnd)); else feedback.setWidget(helpWidget); } private String bold(String s) { return "<b>" + s + "</b>"; } private Widget getHelp() { HorizontalPanel hp = new HorizontalPanel(); GwtUtil.setStyle(hp, "fontSize", "13px"); VerticalPanel vp = new VerticalPanel(); hp.setSpacing(5); // vp.setSpacing(5); hp.add(new HTML("<i>Examples:</i>")); hp.add(vp); vp.add(new HTML("\'m81\' \'ngc 13\' \'12.34 34.89\'" + " \'46.53, -0.251 gal\'")); // vp.add(new HTML("")); HTML line2 = new HTML("\'19h17m32s 11d58m02s equ j2000\' \'12.3, 8.5 b1950\'"); GwtUtil.setStyle(line2, "paddingTop", "4px"); vp.add(line2); return GwtUtil.centerAlign(hp); } private class ResolveTimer extends Timer { @Override public void run() { triggerResolver(false); } public void restart() { this.schedule(500); } } public class ResolveTask extends ServerTask<ResolvedWorldPt> { private final AsyncCallback<ResolvedWorldPt> callback; private final String name; private final Resolver resolver; public ResolveTask(String name, Resolver resolver, AsyncCallback<ResolvedWorldPt> callback) { super(mainPanel, "Resolving...", true); this.name = name; this.resolver = resolver; this.callback = callback; } public String getName() { return name; } public void doTask(AsyncCallback<ResolvedWorldPt> acb) { TargetServices.App.getInstance().resolveName(name, resolver, acb); updateFeedback(ResolveAction.Resolving); } public void onSuccess(ResolvedWorldPt wp) { if (wp != null) { ResolverCache.put(wp, resolver); resolveSuccess(name, wp, callback); _activeTask = null; } else { onFailure(new Exception("Resolve Failed")); } } public void onFailure(Throwable caught) { String msg = caught.getCause() == null ? caught.getMessage() : caught.getCause().getMessage(); posField.forceInvalid("Resolve Failed: " + msg); if (callback != null) callback.onFailure(caught); updateFeedback(ResolveAction.Failed); _activeTask = null; } @Override protected void onCancel(boolean byUser) { if (byUser) { posField.forceInvalid("Resolve Canceled."); updateFeedback(ResolveAction.Failed); if (callback != null) callback.onFailure(null); } _activeTask = null; } } }