package com.eas.ui; import java.util.ArrayList; import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.logging.Level; import java.util.logging.Logger; import com.eas.client.CallbackAdapter; import com.eas.core.HasPublished; import com.eas.core.Utils; import com.eas.form.PlatypusWindow; import com.eas.menu.HasComponentPopupMenu; import com.eas.menu.PlatypusMenu; import com.eas.menu.PlatypusMenuBar; import com.eas.menu.PlatypusPopupMenu; import com.eas.widgets.AnchorsPane; import com.eas.widgets.BorderPane; import com.eas.widgets.BoxPane; import com.eas.widgets.CardPane; import com.eas.widgets.FlowPane; import com.eas.widgets.GridPane; import com.eas.widgets.ScrollPane; import com.eas.widgets.SplitPane; import com.eas.widgets.TabbedPane; import com.eas.widgets.ToolBar; import com.eas.widgets.boxes.DropDownButton; import com.eas.widgets.boxes.ImageButton; import com.google.gwt.core.client.JavaScriptObject; import com.google.gwt.resources.client.ImageResource; import com.google.gwt.user.client.ui.HasEnabled; import com.google.gwt.user.client.ui.HasText; import com.google.gwt.user.client.ui.HasValue; import com.google.gwt.user.client.ui.UIObject; import com.google.gwt.user.client.ui.Widget; import com.google.gwt.xml.client.Element; import com.google.gwt.xml.client.Node; public class DefaultUiReader extends UiReader { protected static class Dimension { public int width; public int height; } protected String rootContainerName; protected Element element; protected Map<String, UIObject> widgets = new HashMap<>(); protected List<UIObject> widgetsList = new ArrayList<>(); protected List<Runnable> resolvers = new ArrayList<>(); protected UIObject viewWidget; protected Utils.JsObject model; public DefaultUiReader(Element anElement, JavaScriptObject aModel) { super(); element = anElement; model = aModel != null ? aModel.<Utils.JsObject> cast() : null; } @Override public Map<String, UIObject> getWidgets() { return widgets; } public List<UIObject> getWidgetsList() { return widgetsList; } public void parse() throws Exception { if (!element.hasAttribute("view")) { throw new IllegalStateException("Old form format detected. Please open the form with a new form designer and re-save it."); } else { rootContainerName = element.getAttribute("view"); Node childNode = element.getFirstChild(); while (childNode != null) { if (childNode instanceof Element) { UIObject widget = readWidget((Element) childNode); if (widget != null) { String wName = ((HasJsName) widget).getJsName(); assert wName != null && !wName.isEmpty() : "A widget is expected to be a named item."; widgets.put(wName, widget); widgetsList.add(widget); } else { Logger.getLogger(DefaultUiReader.class.getName()).log(Level.WARNING, "Unknown widget tag name: " + ((Element) childNode).getTagName() + ". skipping."); } } childNode = childNode.getNextSibling(); } } for (int i = 0; i < resolvers.size(); i++) { Runnable r = resolvers.get(i); r.run(); } viewWidget = widgets.get(rootContainerName); if (viewWidget == null) { viewWidget = new AnchorsPane(); viewWidget.setSize(400 + "px", 300 + "px"); Logger.getLogger(DefaultUiReader.class.getName()).log(Level.WARNING, "view widget missing. Falling back to AnchrosPane."); } } public UIObject getViewWidget() { return viewWidget; } protected Dimension readPrefSize(Element anElement) throws NumberFormatException { if (Utils.hasAttribute(anElement, "pw", "prefWidth") && Utils.hasAttribute(anElement, "ph", "prefHeight")) { Dimension prefSize = new Dimension(); String prefWidth = Utils.getAttribute(anElement, "pw", "prefWidth", null); String prefHeight = Utils.getAttribute(anElement, "ph", "prefHeight", null); if (prefWidth.length() > 2 && prefWidth.endsWith("px")) { prefSize.width = Integer.parseInt(prefWidth.substring(0, prefWidth.length() - 2)); } if (prefHeight.length() > 2 && prefHeight.endsWith("px")) { prefSize.height = Integer.parseInt(prefHeight.substring(0, prefHeight.length() - 2)); } return prefSize; } else return null; } @Override public void addResolver(Runnable aResolver) { resolvers.add(aResolver); } @Override public UIObject readWidget(final Element anElement) throws Exception { for (UiWidgetReader reader : UiReader.getFactories()) { UIObject read = reader.readWidget(anElement, this); if (read != null) { return read; } } return null; } @Override public void readImageParagraph(Element anElement, final UIObject aImageParagraph) throws Exception { if (Utils.hasAttribute(anElement, "i", "icon") && aImageParagraph instanceof HasImageResource) { String iconImage = Utils.getAttribute(anElement, "i", "icon", null); PlatypusImageResource.load(iconImage, new CallbackAdapter<ImageResource, String>() { @Override protected void doWork(ImageResource aResult) throws Exception { ((HasImageResource) aImageParagraph).setImageResource(aResult); } @Override public void onFailure(String reason) { Logger.getLogger(PlatypusWindow.class.getName()).log(Level.SEVERE, "Factory failed to load button icon. " + reason); } }); } if (Utils.hasAttribute(anElement, "tx", "text") && aImageParagraph instanceof HasText) { ((HasText) aImageParagraph).setText(Utils.getAttribute(anElement, "tx", "text", null)); } if (aImageParagraph instanceof HasImageParagraph) { HasImageParagraph hip = (HasImageParagraph) aImageParagraph; hip.setHorizontalAlignment(Utils.getIntegerAttribute(anElement, "ha", "horizontalAlignment", aImageParagraph instanceof ImageButton || aImageParagraph instanceof DropDownButton ? HasImageParagraph.CENTER : HasImageParagraph.LEFT)); hip.setVerticalAlignment(Utils.getIntegerAttribute(anElement, "va", "verticalAlignment", HasImageParagraph.CENTER)); hip.setIconTextGap(Utils.getIntegerAttribute(anElement, "itg", "iconTextGap", 4)); hip.setHorizontalTextPosition(Utils.getIntegerAttribute(anElement, "htp", "horizontalTextPosition", HasImageParagraph.RIGHT)); hip.setVerticalTextPosition(Utils.getIntegerAttribute(anElement, "vtp", "verticalTextPosition", HasImageParagraph.CENTER)); } } @Override public void readGeneralProps(final Element anElement, final UIObject aTarget) throws Exception { String widgetName = ""; if (Utils.hasAttribute(anElement, "n", "name") && aTarget instanceof HasJsName) { widgetName = Utils.getAttribute(anElement, "n", "name", null); ((HasJsName) aTarget).setJsName(widgetName); } /* * if (Utils.hasAttribute(anElement, "e", "editable") && aTarget * instanceof HasEditable) { ((HasEditable) * aTarget).setEditable(Utils.getBooleanAttribute(anElement, "e", * "editable", Boolean.TRUE)); } */ if (Utils.hasAttribute(anElement, "et", "emptyText") && aTarget instanceof HasEmptyText) { ((HasEmptyText) aTarget).setEmptyText(Utils.getAttribute(anElement, "et", "emptyText", null)); } if (aTarget instanceof HasBinding) { if (Utils.hasAttribute(anElement, "f", "field")) { String fieldPath = Utils.getAttribute(anElement, "f", "field", null); try { ((HasBinding) aTarget).setField(fieldPath); } catch (Exception ex) { Logger.getLogger(DefaultUiReader.class.getName()).log(Level.SEVERE, "While setting field (" + fieldPath + ") to widget " + widgetName + " exception occured: " + ex.getMessage()); } } if (Utils.hasAttribute(anElement, "d", "data")) { String entityName = Utils.getAttribute(anElement, "d", "data", null); try { ((HasBinding) aTarget).setData(resolveEntity(entityName)); } catch (Exception ex) { Logger.getLogger(DefaultUiReader.class.getName()).log(Level.SEVERE, "While setting data to named model's property (" + entityName + ") to widget " + widgetName + " exception occured: " + ex.getMessage()); } } } if (aTarget instanceof HasEnabled) ((HasEnabled) aTarget).setEnabled(Utils.getBooleanAttribute(anElement, "en", "enabled", Boolean.TRUE)); // aTarget.setFocusable(Utils.getBooleanAttribute(anElement, "fc", // "focusable", Boolean.TRUE)); if (aTarget instanceof Widget && aTarget instanceof HasPublished) { PublishedComponent pComp = ((HasPublished) aTarget).getPublished().cast(); PublishedFont font = readFont(anElement); if (font != null) { pComp.setFont(font); } if (Utils.hasAttribute(anElement, "o", "opaque")) { pComp.setOpaque(Utils.getBooleanAttribute(anElement, "o", "opaque", Boolean.TRUE)); } if (Utils.hasAttribute(anElement, "bg", "background")) { PublishedColor background = PublishedColor.parse(Utils.getAttribute(anElement, "bg", "background", null)); pComp.setBackground(background); } if (Utils.hasAttribute(anElement, "fg", "foreground")) { PublishedColor foreground = PublishedColor.parse(Utils.getAttribute(anElement, "fg", "foreground", null)); pComp.setForeground(foreground); } if (Utils.hasAttribute(anElement, "ttt", "toolTipText")) { pComp.setToolTipText(Utils.getAttribute(anElement, "ttt", "toolTipText", null)); } } if (Utils.hasAttribute(anElement, "v", "visible")) { aTarget.setVisible(Utils.getBooleanAttribute(anElement, "v", "visible", Boolean.TRUE)); } if (Utils.hasAttribute(anElement, "cpm", "componentPopupMenu") && aTarget instanceof HasComponentPopupMenu) { final String popupName = Utils.getAttribute(anElement, "cpm", "componentPopupMenu", null); if (popupName != null && !popupName.isEmpty()) { resolvers.add(new Runnable() { @Override public void run() { UIObject popup = widgets.get(popupName); if (popup instanceof PlatypusPopupMenu) { ((HasComponentPopupMenu) aTarget).setPlatypusPopupMenu((PlatypusPopupMenu) popup); } } }); } } if (Utils.hasAttribute(anElement, "bgr", "buttonGroup") && aTarget instanceof HasPlatypusButtonGroup) { final String buttonGroupName = Utils.getAttribute(anElement, "bgr", "buttonGroup", null); if (buttonGroupName != null && !buttonGroupName.isEmpty()) { resolvers.add(new Runnable() { @Override public void run() { UIObject buttonGroup = widgets.get(buttonGroupName); if (buttonGroup instanceof ButtonGroup) { ButtonGroup bg = (ButtonGroup) buttonGroup; bg.add((HasValue<Boolean>) aTarget); } } }); } } if (Utils.hasAttribute(anElement, "p", "parent")) { final String parentName = Utils.getAttribute(anElement, "p", "parent", null); if (parentName != null && !parentName.isEmpty()) { resolvers.add(new Runnable() { @Override public void run() { UIObject parent = widgets.get(parentName); try { addToParent(anElement, aTarget, parent); } catch (Exception ex) { Logger.getLogger(DefaultUiReader.class.getName()).log(Level.SEVERE, null, ex); } } }); } } if (aTarget instanceof Widget && aTarget instanceof HasPublished && !(aTarget instanceof PlatypusMenu)) { Dimension prefSize = readPrefSize(anElement); if (prefSize != null) { PublishedComponent pComp = ((HasPublished) aTarget).getPublished().<PublishedComponent> cast(); pComp.setWidth(prefSize.width); pComp.setHeight(prefSize.height); } } } @Override public PublishedFont readFont(Element anElement) throws Exception { PublishedFont font = readFontTag(anElement, "ft", "font"); if (font != null) { return font; } else { return null; } } private PublishedFont readFontTag(Element anElement, String aShortName, String aLongName) throws Exception { Element easFontElement = Utils.scanForElementByTagName(anElement, aShortName, aLongName); if (easFontElement != null) { String name = Utils.getAttribute(easFontElement, "n", "name", null); if (name == null || name.isEmpty() || "null".equals(name)) { name = "Arial"; } int style = Utils.getIntegerAttribute(easFontElement, "stl", "style", 0); int size = Utils.getIntegerAttribute(easFontElement, "sz", "size", 12); return PublishedFont.create(name, style, size); } else { return null; } } private void addToParent(Element anElement, UIObject aTarget, UIObject parent) throws Exception { if (parent instanceof PlatypusMenu) { ((PlatypusMenu) parent).add(aTarget); } else if (parent instanceof PlatypusMenuBar) { ((PlatypusMenuBar) parent).add(aTarget); } else if (parent instanceof PlatypusPopupMenu) { ((PlatypusPopupMenu) parent).add(aTarget); } else if (parent instanceof ToolBar) { ((ToolBar) parent).add((Widget) aTarget); } else if (parent instanceof TabbedPane) { Element constraintsElement = Utils.scanForElementByTagName(anElement, "tpc", "TabbedPaneConstraints"); String tabTitle = Utils.getAttribute(constraintsElement, "tt", "tabTitle", null); String tabIconName = Utils.getAttribute(constraintsElement, "ti", "tabIcon", null); String tabTooltipText = Utils.getAttribute(constraintsElement, "ttp", "tabTooltipText", null); ((TabbedPane) parent).add((Widget) aTarget, tabTitle, false, null); // ((TabbedPane) parent).add(aTarget, tabTitle, // resolveIcon(tabIconName)); } else if (parent instanceof SplitPane) { // Split pane children are: // - left component // - right component // Theese children are setted while resolving component references // of a split pane. } else if (parent instanceof ScrollPane) { ScrollPane scroll = (ScrollPane) parent; // Dimension prefSize = readPrefSize(anElement); // aTarget.setSize(prefSize.width + "px", prefSize.height + "px"); scroll.setWidget((Widget) aTarget); } else if (parent instanceof BorderPane) { Element constraintsElement = Utils.scanForElementByTagName(anElement, "bpc", "BorderPaneConstraints"); Dimension prefSize = readPrefSize(anElement); Integer place = Utils.getIntegerAttribute(constraintsElement, "pl", "place", HorizontalPosition.CENTER); Integer size = 0; switch (place) { case HorizontalPosition.LEFT: size = prefSize.width; break; case HorizontalPosition.RIGHT: size = prefSize.width; break; case VerticalPosition.TOP: size = prefSize.height; break; case VerticalPosition.BOTTOM: size = prefSize.height; break; } BorderPane borderPane = (BorderPane) parent; borderPane.add((Widget) aTarget, place, size); } else if (parent instanceof BoxPane) { Dimension prefSize = readPrefSize(anElement); BoxPane box = (BoxPane) parent; if (box.getOrientation() == Orientation.HORIZONTAL) { box.add((Widget) aTarget, prefSize.width); } else { box.add((Widget) aTarget, prefSize.height); } } else if (parent instanceof CardPane) { Element constraintsElement = Utils.scanForElementByTagName(anElement, "cpc", "CardPaneConstraints"); String cardName = Utils.getAttribute(constraintsElement, "cn", "cardName", null); ((CardPane) parent).add((Widget) aTarget, cardName); } else if (parent instanceof FlowPane) { // Dimension prefSize = readPrefSize(anElement); // aTarget.setSize(prefSize.width + "px", prefSize.height + "px"); ((FlowPane) parent).add((Widget) aTarget); } else if (parent instanceof GridPane) { GridPane gridPane = (GridPane) parent; gridPane.addToFreeCell((Widget) aTarget); } else if (parent instanceof AnchorsPane) { Element constraintsElement = Utils.scanForElementByTagName(anElement, "apc", "AnchorsPaneConstraints"); MarginConstraints constraints = readMarginConstraints(constraintsElement); ((AnchorsPane) parent).add((Widget) aTarget, constraints); } } @Override public Utils.JsObject resolveEntity(String aEntityName) throws Exception { if (model.has(aEntityName)) { JavaScriptObject oEntity = model.getJs(aEntityName); if (oEntity != null) { return oEntity.cast(); } } return null; } private static MarginConstraints readMarginConstraints(Element anElement) { MarginConstraints result = new MarginConstraints(); if (Utils.hasAttribute(anElement, "l", "left")) { result.setLeft(MarginConstraints.Margin.parse(Utils.getAttribute(anElement, "l", "left", null))); } if (Utils.hasAttribute(anElement, "r", "right")) { result.setRight(MarginConstraints.Margin.parse(Utils.getAttribute(anElement, "r", "right", null))); } if (Utils.hasAttribute(anElement, "t", "top")) { result.setTop(MarginConstraints.Margin.parse(Utils.getAttribute(anElement, "t", "top", null))); } if (Utils.hasAttribute(anElement, "b", "bottom")) { result.setBottom(MarginConstraints.Margin.parse(Utils.getAttribute(anElement, "b", "bottom", null))); } if (Utils.hasAttribute(anElement, "w", "width")) { result.setWidth(MarginConstraints.Margin.parse(Utils.getAttribute(anElement, "w", "width", null))); } if (Utils.hasAttribute(anElement, "h", "height")) { result.setHeight(MarginConstraints.Margin.parse(Utils.getAttribute(anElement, "h", "height", null))); } return result; } }