/* (non-Javadoc) * @see de.enough.polish.browser.TagHandler#handleTag(de.enough.polish.ui.Container, de.enough.polish.xml.PullParser, java.lang.String, boolean, de.enough.polish.util.HashMap, de.enough.polish.ui.Style) */ public boolean handleTag( Container parentItem, SimplePullParser parser, String tagName, boolean opening, HashMap attributeMap, Style style) { // #debug System.out.println((opening ? "<" : "</") + tagName + ">"); tagName = tagName.toLowerCase(); if (TAG_DIV.equals(tagName) || TAG_SPAN.equals(tagName)) { if (opening) { String itemStyleName = (String) attributeMap.get("textclass"); Style itemStyle = (itemStyleName == null ? null : StyleSheet.getStyle(itemStyleName)); if (itemStyle != null) { this.textStyle = itemStyle; } if (this.isDivOrSpanOpened == null) { this.isDivOrSpanOpened = new BooleanStack(); } // System.out.println("opening <div> with style " + (style == null ? null : style.name)); if (style != null) { this.browser.openContainer(style); } this.isDivOrSpanOpened.push(style != null); // this.browser.openContainer( style ); // this.isDivOrSpanOpened.push( true ); } else { this.textStyle = null; // System.out.println("closing <div> with container=" + this.isDivOrSpanOpened.peek()); if (this.isDivOrSpanOpened.pop()) { Container container = this.browser.closeContainer(); if (UiAccess.cast(container) instanceof TableItem) { this.currentTable = (TableItem) UiAccess.cast(container); } } // Style divStyle = container.getStyle(); // if (divStyle != null) { // Object[] items = container.getInternalArray(); // for (int i = 0; i < items.length; i++) // { // Item item = (Item) items[i]; // if (item == null) { // break; // } // item.setStyle( divStyle ); // } // } } } else if (TAG_SELECT.equals(tagName)) { if (opening) { if (this.currentSelect != null) { // #debug error System.out.println( "Error in HTML-Code: You cannot open a <select>-tag inside another <select>-tag."); ChoiceGroup choiceGroup = this.currentSelect.getChoiceGroup(); add(choiceGroup); if (this.currentForm == null) { // #debug error System.out.println("Error in HTML-Code: no <form> for <select> element found!"); } else { this.currentForm.addItem(choiceGroup); } this.currentSelect = null; } String name = parser.getAttributeValue(ATTR_NAME); String sizeStr = parser.getAttributeValue(ATTR_SIZE); int size; try { size = Integer.parseInt(sizeStr); } catch (NumberFormatException e) { size = -1; } boolean isMultiple = parser.getAttributeValue(ATTR_MULTIPLE) != null; this.currentSelect = new HtmlSelect(name, size, isMultiple, style); } else { // tag is closed if (this.currentSelect != null) { ChoiceGroup choiceGroup = this.currentSelect.getChoiceGroup(); add(choiceGroup); if (this.currentForm == null) { // #debug error System.out.println("Error in HTML-Code: no <form> for <select> element found!"); } else { this.currentForm.addItem(choiceGroup); } this.currentSelect = null; } // #mdebug error else { // #debug error System.out.println( "Error in HTML-Code. You cannot close a <select>-tag without opening one."); } // #enddebug } return true; } else if (TAG_OPTION.equals(tagName)) { if (this.currentSelect != null && opening) { // TODO: handle "selected" attribute. String value = parser.getAttributeValue(ATTR_VALUE); String selected = parser.getAttributeValue("selected"); parser.next(); String name = handleText(parser.getText()); if (value == null) { value = name; } this.currentSelect.addOption(name, value, selected != null, style); } return true; } else if (TAG_A.equals(tagName)) { if (opening) { this.anchorHref = (String) attributeMap.get(ATTR_HREF); // #if polish.debug.error if (this.anchorHref == null) { // #debug error System.out.println( "Unable to handle anchor tag <a> without " + ATTR_HREF + " attribute: " + attributeMap); } // #endif this.browser.openContainer(style); if (style == null) { Container container = this.browser.getCurrentContainer(); // #style browserLink UiAccess.setStyle(container); } } else { // apply link to last item(s): Container container = this.browser.removeCurrentContainer(); Style contStyle = container.getStyle(); Item linkItem; if (container.size() == 0) { linkItem = new StringItem(null, null); } else if (container.size() == 1) { linkItem = container.get(0); } else { // check if all elements are StringItems - then we should combine them: boolean allItemsAreStringItems = true; StringBuffer text = new StringBuffer(); for (int i = 0; i < container.size(); i++) { Item item = container.get(i); if (!(item instanceof StringItem)) { allItemsAreStringItems = false; break; } else { if (text.length() > 0) { text.append(' '); } text.append(((StringItem) item).getText()); } } if (allItemsAreStringItems) { linkItem = new StringItem(null, text.toString()); } else { linkItem = container; } } // System.out.println("closing <a>: container.size()=" + container.size() + ", linkItem=" // + linkItem + ", style=" + (contStyle != null ? contStyle.name : "<no style>") ); if (this.anchorHref != null) { if (contStyle != null) { linkItem.setStyle(contStyle); } else if (linkItem.getStyle() == null) { // #style browserLink UiAccess.setStyle(linkItem); } linkItem.setDefaultCommand(CMD_LINK); linkItem.setItemCommandListener(this); linkItem.setAttribute(ATTR_HREF, this.anchorHref); addCommands(TAG_A, linkItem); add(linkItem); } // this.browser.closeContainer(); } } if (opening) { // if (TAG_A.equals(tagName)) // { // String href = (String) attributeMap.get(ATTR_HREF); // parser.next(); // Item linkItem; // if (href != null) // { // String anchorText = handleText(parser.getText()); // // hack for image links: // if ("".equals(anchorText) && TAG_IMG.equals(parser.getName())) { // // this is an image link: // attributeMap.clear(); // for (int i = 0; i < parser.getAttributeCount(); i++) // { // String attributeName = parser.getAttributeName(i); // String attributeValue = parser.getAttributeValue(i); // attributeMap.put(attributeName, attributeValue); // } // String src = (String) attributeMap.get("src"); // String url = this.browser.makeAbsoluteURL(src); // Image image = this.browser.loadImage(url); // //#style browserLink // linkItem = new ImageItem(null, image, 0, (String) attributeMap.get("alt") ); // //this.browser.loadImageLater( url, (ImageItem) linkItem ); // // } else { // //#style browserLink // linkItem = new StringItem(null, anchorText); // } // linkItem.setDefaultCommand(CMD_LINK); // linkItem.setItemCommandListener( this ); // linkItem.setAttribute(ATTR_HREF, href ); // addCommands(TAG_A, linkItem); // } // else // { // //#style browserText // linkItem = new StringItem(null, handleText(parser.getText())); // } // if (style != null) { // linkItem.setStyle(style); // } // add(linkItem); // return true; // } // else if (TAG_BR.equals(tagName)) { addLineBreak(); return true; } else if (TAG_P.equals(tagName)) { addLineBreak(); if (opening) { this.textStyle = style; } return true; } else if (TAG_IMG.equals(tagName)) { String src = (String) attributeMap.get("src"); String url = this.browser.makeAbsoluteURL(src); Dimension width = parseSizeValue((String) attributeMap.get("width")); Dimension height = parseSizeValue((String) attributeMap.get("height")); Style imageStyle = new Style(); imageStyle.addAttribute(58 /* "min-width" */, width); imageStyle.addAttribute(144 /* "min-height" */, height); ImageItem item; if (width != null || height != null) { item = new ScaledImageItem(null, null, width, height, Item.LAYOUT_DEFAULT, ""); } else { item = new ImageItem(null, null, Item.LAYOUT_DEFAULT, ""); } if (imageStyle != null) { item.setStyle(imageStyle); } this.browser.loadImageLater(item, url); add(item); return true; } else if (TAG_TITLE.equals(tagName)) { // Hack to read title. parser.next(); String name = handleText(parser.getText()); Screen myScreen = this.browser.getScreen(); if (name != null && myScreen != null) { myScreen.setTitle(name); } return true; } else if (TAG_STYLE.equals(tagName)) { // Hack to read style content. parser.next(); String cssCode = parser.getText(); try { CssInterpreter reader = new CssInterpreter(cssCode, this.browser); this.browser.setCssStyles(reader.getAllStyles()); } catch (Exception e) { // #debug error System.out.println("Unable to parse CSS" + e); } // parser.next(); return true; } else if (TAG_META.equals(tagName)) { String httpEquiv = (String) attributeMap.get("http-equiv"); if (httpEquiv != null && TextUtil.equalsIgnoreCase("refresh", httpEquiv)) { String content = (String) attributeMap.get("content"); if (content != null) { int semicolonPos = content.indexOf(';'); int waitTime = 0; String url = content; if (semicolonPos != -1) { try { waitTime = Integer.parseInt(content.substring(0, semicolonPos)); url = content.substring(semicolonPos + 1); } catch (Exception e) { if (semicolonPos == 0) { url = content.substring(1); } } } int equalsPos = url.indexOf('='); if (equalsPos != -1) { url = url.substring(equalsPos + 1).trim(); } if (url.indexOf(':') == -1) { // assuming resource protocol: if (url.charAt(0) != '/') { url = "resource://" + url; } else { url = "resource:/" + url; } } if (waitTime > 0) { (new RedirectThread(this.browser, waitTime * 1000L, url)).start(); } else { // consume rest of document: while (parser.next() != SimplePullParser.END_DOCUMENT) { // read document.. } this.browser.go(url); } return true; } } return false; } // #if polish.Browser.supportTextInput != false else if (TAG_TEXT_AREA.equals(tagName)) { parser.next(); String value = handleText(parser.getText()); int maxCharNumber = 500; String cols = (String) attributeMap.get("cols"); String rows = (String) attributeMap.get("rows"); if (cols != null && rows != null) { try { maxCharNumber = Integer.parseInt(cols) * Integer.parseInt(rows); } catch (Exception e) { // #debug error System.out.println( "Unable to parse textarea cols or rows attribute: cols=" + cols + ", rows=" + rows); } } // #style browserInput TextField textField = new TextField(null, value, maxCharNumber, TextField.ANY); if (style != null) { textField.setStyle(style); } add(textField); if (this.currentForm != null) { this.currentForm.addItem(textField); textField.setAttribute(ATTR_FORM, this.currentForm); String name = (String) attributeMap.get(INPUT_NAME); if (value == null) { value = name; } if (name != null) { textField.setAttribute(ATTR_NAME, name); textField.setAttribute(ATTR_VALUE, value); } } return true; } // #endif else if (TAG_BUTTON.equals(tagName) && this.currentForm != null) { String name = (String) attributeMap.get(INPUT_NAME); String value = (String) attributeMap.get(INPUT_VALUE); if (value == null) { value = name; } // #style browserLink StringItem buttonItem = new StringItem(null, value); if (style != null) { buttonItem.setStyle(style); } buttonItem.setDefaultCommand(CMD_SUBMIT); buttonItem.setItemCommandListener(this); addCommands(TAG_INPUT, INPUT_TYPE, INPUTTYPE_SUBMIT, buttonItem); add(buttonItem); this.currentForm.addItem(buttonItem); buttonItem.setAttribute(ATTR_FORM, this.currentForm); buttonItem.setAttribute(ATTR_TYPE, "submit"); if (name != null) { buttonItem.setAttribute(ATTR_NAME, name); buttonItem.setAttribute(ATTR_VALUE, value); } } else if (TAG_INPUT.equals(tagName)) { if (this.currentForm != null) { String type = (String) attributeMap.get(INPUT_TYPE); String name = (String) attributeMap.get(INPUT_NAME); String value = (String) attributeMap.get(INPUT_VALUE); if (type != null) { type = type.toLowerCase(); } if (this.formListener != null && name != null) { value = this.formListener.verifyInitialFormValue(this.currentForm.getAction(), name, value); } // #if polish.Browser.supportTextInput != false if (INPUTTYPE_TEXT.equals(type) || INPUTTYPE_PASSWORD.equals(type) || INPUTTYPE_NUMERIC.equals(type)) { int constraints; if (INPUTTYPE_NUMERIC.equals(type)) { constraints = TextField.NUMERIC; } else { constraints = INPUTTYPE_TEXT.equals(type) ? TextField.ANY : TextField.PASSWORD; } // #style browserInput TextField textField = new TextField((String) attributeMap.get("label"), value, 100, constraints); if (style != null) { textField.setStyle(style); } add(textField); this.currentForm.addItem(textField); textField.setAttribute(ATTR_FORM, this.currentForm); if (name != null) { textField.setAttribute(ATTR_NAME, name); if (value == null) { value = ""; } textField.setAttribute(ATTR_VALUE, value); } } else // #endif if (INPUTTYPE_SUBMIT.equals(type)) { if (value == null) { value = name; } // #style browserLink StringItem buttonItem = new StringItem((String) attributeMap.get("label"), value); if (style != null) { buttonItem.setStyle(style); } buttonItem.setDefaultCommand(CMD_SUBMIT); buttonItem.setItemCommandListener(this); addCommands(TAG_INPUT, INPUT_TYPE, INPUTTYPE_SUBMIT, buttonItem); add(buttonItem); this.currentForm.addItem(buttonItem); buttonItem.setAttribute(ATTR_FORM, this.currentForm); buttonItem.setAttribute(ATTR_TYPE, "submit"); if (name != null) { buttonItem.setAttribute(ATTR_NAME, name); buttonItem.setAttribute(ATTR_VALUE, value); } } else if (INPUTTYPE_HIDDEN.equals(type)) { this.currentForm.addHiddenElement(name, value); } else if (INPUTTYPE_CHECKBOX.equals(type) || INPUTTYPE_RADIO.equals(type)) { boolean isCheckBox = INPUTTYPE_CHECKBOX.equals(type); parser.next(); String label = parser.getText().trim(); int labelLength = label.length(); if (labelLength == 0) { parser.next(); label = parser.getText().trim(); labelLength = label.length(); } if ((labelLength > 0) && label.charAt(labelLength - 1) == '\n') { label = label.substring(0, labelLength - 1); } ChoiceGroup choiceGroup; if (isCheckBox) { choiceGroup = this.currentCheckBoxChoiceGroup; } else { choiceGroup = this.currentRadioChoiceGroup; } if (choiceGroup == null || !name.equals(choiceGroup.getAttribute(ATTR_NAME))) { // create a new choice group: String groupLabel = (String) attributeMap.get("label"); if (isCheckBox) { // #style browserChoiceGroupMultiple choiceGroup = new ChoiceGroup(groupLabel, Choice.MULTIPLE); } else { String choiceType = (String) attributeMap.get("choice"); if ("popup".equals(choiceType)) { // #style browserChoiceGroupPopup choiceGroup = new ChoiceGroup(groupLabel, Choice.POPUP); this.currentRadioChoiceGroup = choiceGroup; } else { // #style browserChoiceGroupExclusive choiceGroup = new ChoiceGroup(groupLabel, Choice.EXCLUSIVE); this.currentRadioChoiceGroup = choiceGroup; } } choiceGroup.setAttribute(ATTR_NAME, name); String styleName = (String) attributeMap.get("groupclass"); if (styleName != null) { Style groupStyle = StyleSheet.getStyle(styleName); if (groupStyle != null) { choiceGroup.setStyle(groupStyle); } } add(choiceGroup); if (this.currentForm == null) { // #debug error System.out.println("Error in HTML-Code: no <form> for <select> element found!"); } else { this.currentForm.addItem(choiceGroup); } // end of creating a new choice group } ChoiceItem item; if (isCheckBox) { // #style browserCheckBox item = new ChoiceItem(label, null, Choice.MULTIPLE); } else { // #style browserRadio item = new ChoiceItem(label, null, choiceGroup.getType()); } item.setAttribute(ATTR_VALUE, value); choiceGroup.append(item); if (attributeMap.get("checked") != null) { choiceGroup.setSelectedIndex(choiceGroup.size() - 1, true); } if (style != null) { item.setStyle(style); } } // #if polish.debug.debug else { // #debug System.out.println("unhandled html form input type: " + type); } // #endif } return true; } else if (TAG_SCRIPT.equals(tagName)) { // Consume javascript code. parser.next(); return true; } else if (TAG_TABLE.equals(tagName)) { // #style browserTable? TableItem table = new TableItem(); table.setSelectionMode( TableItem.SELECTION_MODE_CELL | TableItem.SELECTION_MODE_INTERACTIVE); table.setCellContainerStyle(this.browser.getStyle()); if (style != null) { table.setStyle(style); } this.currentTable = table; this.browser.openContainer(table); return true; } else if (this.currentTable != null && TAG_TR.equals(tagName)) { this.currentTable.moveToNextRow(); return true; } else if (this.currentTable != null && TAG_TH.equals(tagName)) { // TODO differentiate between th and td this.currentTable.moveToNextColumn(); return true; } else if (this.currentTable != null && TAG_TD.equals(tagName)) { // TODO differentiate between th and td this.currentTable.moveToNextColumn(); return true; } else if (TAG_CODE.equals(tagName)) { // #if polish.css.style.browsertextcode && !polish.LibraryBuild // #style browserTextCode // # this.textStyle = (); // #endif } } else { // the tag is being closed: if (TAG_TABLE.equals(tagName)) { Container container = this.browser.closeContainer(); if (UiAccess.cast(container) instanceof TableItem) { this.currentTable = (TableItem) UiAccess.cast(container); } else { this.currentTable = null; } return true; } if (TAG_CODE.equals(tagName)) { this.textStyle = null; } } if (TAG_B.equals(tagName) || TAG_STRONG.equals(tagName)) { this.textBold = opening; return true; } else if (TAG_I.equals(tagName) || TAG_EM.equals(tagName)) { this.textItalic = opening; return true; } else if (TAG_FORM.equals(tagName)) { if (opening) { String name = (String) attributeMap.get("name"); String action = (String) attributeMap.get("action"); String method = (String) attributeMap.get("method"); String encoding = (String) attributeMap.get("enctype"); if (method == null) { method = "GET"; } this.currentForm = new HtmlForm(name, action, method, encoding, this.browser, this.formListener); this.browser.addForm(this.currentForm); this.browser.openContainer(style); } else { this.browser.closeContainer(); this.currentForm = null; this.currentCheckBoxChoiceGroup = null; this.currentRadioChoiceGroup = null; } return true; } else if (opening && TAG_BODY.equals(tagName)) { if (style != null) { // System.out.println("applying style " + style.name + " for body with bg=" + // style.background); this.browser.setBackground(style.background); this.browser.setBorder(style.border); this.browser.setStyle(style, false); } } return false; }