diff --git a/org.hl7.fhir.utilities/src/main/java/org/hl7/fhir/utilities/i18n/RenderingI18nContext.java b/org.hl7.fhir.utilities/src/main/java/org/hl7/fhir/utilities/i18n/RenderingI18nContext.java index f8c0e34c3..4b054001d 100644 --- a/org.hl7.fhir.utilities/src/main/java/org/hl7/fhir/utilities/i18n/RenderingI18nContext.java +++ b/org.hl7.fhir.utilities/src/main/java/org/hl7/fhir/utilities/i18n/RenderingI18nContext.java @@ -1,5 +1,6 @@ package org.hl7.fhir.utilities.i18n; + public class RenderingI18nContext extends I18nBase { public static final String ACTOR_DEF_ACT = "ACTOR_DEF_ACT"; @@ -931,6 +932,19 @@ public class RenderingI18nContext extends I18nBase { public static final String MATURITY_MATURITY = "MATURITY_MATURITY"; public static final String MATURITY_STDS_STATUS = "MATURITY_STDS_STATUS"; + public static final String DATA_REND_MORNING = "DATA_REND_MORNING"; + public static final String DATA_REND_MORNING_EARLY = "DATA_REND_MORNING_EARLY"; + public static final String DATA_REND_MORNING_LATE = "DATA_REND_MORNING_LATE"; + public static final String DATA_REND_NOON = "DATA_REND_NOON"; + public static final String DATA_REND_AFTERNOON = "DATA_REND_AFTERNOON"; + public static final String DATA_REND_AFTERNOON_EARLY = ""; + public static final String DATA_REND_AFTERNOON_LATE = "DATA_REND_AFTERNOON_LATE"; + public static final String DATA_REND_EVENING = "DATA_REND_EVENING"; + public static final String DATA_REND_EVENING_EARLY = ""; + public static final String DATA_REND_EVENING_LATE = "DATA_REND_EVENING_LATE"; + public static final String DATA_REND_NIGHT = "DATA_REND_NIGHT"; + public static final String DATA_REND_AFTER_SLEEP = "DATA_REND_AFTER_SLEEP"; + public static final String DATA_REND_IMMEDIATE = "DATA_REND_IMMEDIATE"; protected String getMessagesSourceFileName() { return "rendering-phrases"; diff --git a/org.hl7.fhir.utilities/src/main/java/org/hl7/fhir/utilities/xhtml/HierarchicalTableGenerator.java b/org.hl7.fhir.utilities/src/main/java/org/hl7/fhir/utilities/xhtml/HierarchicalTableGenerator.java index d743f1c7a..0554f12de 100644 --- a/org.hl7.fhir.utilities/src/main/java/org/hl7/fhir/utilities/xhtml/HierarchicalTableGenerator.java +++ b/org.hl7.fhir.utilities/src/main/java/org/hl7/fhir/utilities/xhtml/HierarchicalTableGenerator.java @@ -250,6 +250,7 @@ public class HierarchicalTableGenerator { private List pieces = new ArrayList(); private String cellStyle; protected int span = 1; + private boolean innerTable; // if you want a multiline left cell, you have to set this to true private TextAlignment alignment = TextAlignment.LEFT; private String id; @@ -271,17 +272,19 @@ public class HierarchicalTableGenerator { pieces.add(piece); return this; } - - public Cell addMarkdown(String md) { + return addMarkdown(md, null); + } + + public Cell addMarkdown(String md, String style) { if (!Utilities.noString(md)) { try { Parser parser = Parser.builder().build(); Node document = parser.parse(md); HtmlRenderer renderer = HtmlRenderer.builder().escapeHtml(true).build(); String html = renderer.render(document); - pieces.addAll(htmlToParagraphPieces(html, null)); + pieces.addAll(htmlToParagraphPieces(html, style)); } catch (Exception e) { e.printStackTrace(); } @@ -405,12 +408,22 @@ public class HierarchicalTableGenerator { } return piece; } - + public Cell addStyle(String style) { for (Piece p : pieces) p.addStyle(style); return this; } + + public Cell addCellStyle(String style) { + if (cellStyle == null) { + cellStyle = style; + } else { + cellStyle = cellStyle+"; "+style; + } + return this; + } + public void addToHint(String text) { for (Piece p : pieces) p.addToHint(text); @@ -472,6 +485,25 @@ public class HierarchicalTableGenerator { public void setId(String id) { this.id = id; } + public Piece addImg(String icon, String hint, String link) { + Piece p = new Piece("img"); + p.attr("src", icon); + p.hint = hint; + p.reference = link; + pieces.add(p); + return p; + } + public void addXhtml(XhtmlNode div) { + Piece p = new Piece(null); + pieces.add(p); + p.children = div.childNodes; + } + public boolean isInnerTable() { + return innerTable; + } + public void setInnerTable(boolean innerTable) { + this.innerTable = innerTable; + } } @@ -505,6 +537,8 @@ public class HierarchicalTableGenerator { private int lineColor; private String id; private String opacity; + private String topLine; + private boolean partnerRow; public List getSubRows() { return subRows; @@ -561,6 +595,13 @@ public class HierarchicalTableGenerator { } return b.toString(); } + public String getTopLine() { + return topLine; + } + public void setTopLine(String topLine) { + this.topLine = topLine; + } + } public class TableModel { @@ -571,6 +612,8 @@ public class HierarchicalTableGenerator { private String docoRef; private String docoImg; private boolean alternating; + private boolean showHeadings = true; + private boolean border = false; public TableModel(String id, boolean active) { super(); @@ -611,6 +654,18 @@ public class HierarchicalTableGenerator { public void setAlternating(boolean alternating) { this.alternating = alternating; } + public boolean isShowHeadings() { + return showHeadings; + } + public void setShowHeadings(boolean showHeadings) { + this.showHeadings = showHeadings; + } + public boolean isBorder() { + return border; + } + public void setBorder(boolean border) { + this.border = border; + } } @@ -630,6 +685,7 @@ public class HierarchicalTableGenerator { private TableGenerationMode mode; private RenderingI18nContext i18n; private String uniqueLocalPrefix; + private boolean treelines = true; public HierarchicalTableGenerator(RenderingI18nContext i18n) { super(); @@ -724,6 +780,7 @@ public class HierarchicalTableGenerator { return model; } + public TableModel initComparisonTable(String prefix, String id) throws IOException { TableModel model = new TableModel(id, true); @@ -762,38 +819,45 @@ public class HierarchicalTableGenerator { public XhtmlNode generate(TableModel model, String imagePath, int border, Set outputTracker) throws IOException, FHIRException { checkModel(model); XhtmlNode table = new XhtmlNode(NodeType.Element, "table").setAttribute("border", Integer.toString(border)).setAttribute("cellspacing", "0").setAttribute("cellpadding", "0"); - + table.setAttribute("fhir", "generated-heirarchy"); if (model.isActive()) { table.setAttribute("id", model.getId()); } - table.setAttribute("style", "border: " + border + "px #F0F0F0 solid; font-size: 11px; font-family: verdana; vertical-align: top;"); - XhtmlNode tr = table.addTag("tr"); - tr.setAttribute("style", "border: " + Integer.toString(1 + border) + "px #F0F0F0 solid; font-size: 11px; font-family: verdana; vertical-align: top"); - XhtmlNode tc = null; - for (Title t : model.getTitles()) { - tc = renderCell(tr, t, "th", null, null, null, false, null, "white", 0, imagePath, border, outputTracker, model, null, true); - if (t.width != 0) - tc.setAttribute("style", "width: "+Integer.toString(t.width)+"px"); + if (model.isBorder()) { + table.setAttribute("style", "border: 2px black solid; font-size: 11px; font-family: verdana; vertical-align: top;"); + } else { + table.setAttribute("style", "border: " + border + "px #F0F0F0 solid; font-size: 11px; font-family: verdana; vertical-align: top;"); } - if (tc != null && model.getDocoRef() != null) { - XhtmlNode a = tc.addTag("span").setAttribute("style", "float: right").addTag("a").setAttribute("title", "Legend for this format").setAttribute("href", model.getDocoRef()); - if (mode == TableGenerationMode.XHTML) { - a.setAttribute("no-external", "true"); + if (model.isShowHeadings()) { + XhtmlNode tr = table.addTag("tr"); + tr.setAttribute("fhir", "generated-heirarchy"); + tr.setAttribute("style", "border: " + Integer.toString(1 + border) + "px #F0F0F0 solid; font-size: 11px; font-family: verdana; vertical-align: top"); + XhtmlNode tc = null; + for (Title t : model.getTitles()) { + tc = renderCell(tr, t, "th", null, null, null, false, null, "white", 0, imagePath, border, outputTracker, model, null, true); + if (t.width != 0) + tc.setAttribute("style", "width: "+Integer.toString(t.width)+"px"); } - XhtmlNode img = a.addTag("img"); - img.setAttribute("alt", "doco").setAttribute("style", "background-color: inherit").setAttribute("src", model.getDocoImg()); - if (model.isActive()) { - img.setAttribute("onLoad", "fhirTableInit(this)"); + if (tc != null && model.getDocoRef() != null) { + XhtmlNode a = tc.addTag("span").setAttribute("style", "float: right").addTag("a").setAttribute("title", "Legend for this format").setAttribute("href", model.getDocoRef()); + if (mode == TableGenerationMode.XHTML) { + a.setAttribute("no-external", "true"); + } + XhtmlNode img = a.addTag("img"); + img.setAttribute("alt", "doco").setAttribute("style", "background-color: inherit").setAttribute("src", model.getDocoImg()); + if (model.isActive()) { + img.setAttribute("onLoad", "fhirTableInit(this)"); + } } } - Counter counter = new Counter(); for (Row r : model.getRows()) { renderRow(table, r, 0, new ArrayList(), imagePath, border, outputTracker, counter, model); } if (model.getDocoRef() != null) { - tr = table.addTag("tr"); - tc = tr.addTag("td"); + XhtmlNode tr = table.addTag("tr"); + tr.setAttribute("fhir", "generated-heirarchy"); + XhtmlNode tc = tr.addTag("td"); tc.setAttribute("class", "hierarchy"); tc.setAttribute("colspan", Integer.toString(model.getTitles().size())); tc.addTag("br"); @@ -807,15 +871,21 @@ public class HierarchicalTableGenerator { private void renderRow(XhtmlNode table, Row r, int indent, List indents, String imagePath, int border, Set outputTracker, Counter counter, TableModel model) throws IOException { - counter.row(); + if (!r.partnerRow) { + counter.row(); + } XhtmlNode tr = table.addTag("tr"); + tr.setAttribute("fhir", "generated-heirarchy"); + String color = "white"; if (r.getColor() != null) color = r.getColor(); else if (model.isAlternating() && counter.isOdd()) color = BACKGROUND_ALT_COLOR; - tr.setAttribute("style", "border: " + border + "px #F0F0F0 solid; padding:0px; vertical-align: top; background-color: "+color+(r.getOpacity() == null ? "" : "; opacity: "+r.getOpacity())); + String lineStyle = r.getTopLine() == null ? "" : "; border-top: 1px solid "+r.getTopLine(); + + tr.setAttribute("style", "border: " + border + "px #F0F0F0 solid; padding:0px; vertical-align: top; background-color: "+color+(r.getOpacity() == null ? "" : "; opacity: "+r.getOpacity())+lineStyle); if (model.isActive()) { tr.setAttribute("id", r.getId()); } @@ -848,26 +918,34 @@ public class HierarchicalTableGenerator { } if (c.getId() != null) { tc.setAttribute("id", c.getId()); + } + String lineStyle = row != null && row.getTopLine() == null ? "" : "; padding-top: 3px; padding-bottom: 3px"; + + XhtmlNode itc = tc; + XhtmlNode itr = null; + if (c.innerTable) { + itr = tc.table("none").tr(); + itc = itr.td(); } if (indents != null) { - tc.addTag("img").setAttribute("src", srcFor(imagePath, "tbl_spacer.png")).setAttribute("style", "background-color: inherit").setAttribute("class", "hierarchy").setAttribute("alt", "."); - tc.setAttribute("style", "vertical-align: top; text-align : left; "+(c.cellStyle != null && c.cellStyle.contains("background-color") ? "" : "background-color: "+color+"; ")+"border: "+ border +"px #F0F0F0 solid; padding:0px 4px 0px 4px; white-space: nowrap; background-image: url("+imagePath+checkExists(indents, hasChildren, lineColor, outputTracker)+")"+(c.cellStyle != null ? ";"+c.cellStyle : "")); + itc.addTag("img").setAttribute("src", srcFor(imagePath, "tbl_spacer.png")).setAttribute("style", "background-color: inherit").setAttribute("class", "hierarchy").setAttribute("alt", "."); + tc.setAttribute("style", "vertical-align: top; text-align : left; "+(c.cellStyle != null && c.cellStyle.contains("background-color") ? "" : "background-color: "+color+"; ")+"border: "+ border +"px #F0F0F0 solid; padding:0px 4px 0px 4px; white-space: nowrap"+(treelines ? "; background-image: url("+imagePath+checkExists(indents, hasChildren, lineColor, outputTracker)+")" : "")+(c.cellStyle != null ? ";"+c.cellStyle : "")+lineStyle); for (int i = 0; i < indents.size()-1; i++) { switch (indents.get(i)) { case NEW_REGULAR: case NEW_SLICER: case NEW_SLICE: - tc.addTag("img").setAttribute("src", srcFor(imagePath, "tbl_blank.png")).setAttribute("style", "background-color: inherit").setAttribute("class", "hierarchy").setAttribute("alt", "."); + itc.addTag("img").setAttribute("src", srcFor(imagePath, "tbl_blank.png")).setAttribute("style", "background-color: inherit").setAttribute("class", "hierarchy").setAttribute("alt", "."); break; case CONTINUE_REGULAR: - tc.addTag("img").setAttribute("src", srcFor(imagePath, "tbl_vline.png")).setAttribute("style", "background-color: inherit").setAttribute("class", "hierarchy").setAttribute("alt", "."); + itc.addTag("img").setAttribute("src", srcFor(imagePath, "tbl_vline.png")).setAttribute("style", "background-color: inherit").setAttribute("class", "hierarchy").setAttribute("alt", "."); break; case CONTINUE_SLICER: - tc.addTag("img").setAttribute("src", srcFor(imagePath, "tbl_vline_slicer.png")).setAttribute("style", "background-color: inherit").setAttribute("class", "hierarchy").setAttribute("alt", "."); + itc.addTag("img").setAttribute("src", srcFor(imagePath, "tbl_vline_slicer.png")).setAttribute("style", "background-color: inherit").setAttribute("class", "hierarchy").setAttribute("alt", "."); break; case CONTINUE_SLICE: - tc.addTag("img").setAttribute("src", srcFor(imagePath, "tbl_vline_slice.png")).setAttribute("style", "background-color: inherit").setAttribute("class", "hierarchy").setAttribute("alt", "."); + itc.addTag("img").setAttribute("src", srcFor(imagePath, "tbl_vline_slice.png")).setAttribute("style", "background-color: inherit").setAttribute("class", "hierarchy").setAttribute("alt", "."); break; default: throw new Error("Unrecognized indent level: " + indents.get(i)); @@ -875,7 +953,7 @@ public class HierarchicalTableGenerator { } if (!indents.isEmpty()) { String sfx = table.isActive() && hasChildren ? "-open" : ""; - XhtmlNode img = tc.addTag("img"); + XhtmlNode img = itc.addTag("img"); switch (indents.get(indents.size()-1)) { case NEW_REGULAR: img.setAttribute("src", srcFor(imagePath, "tbl_vjoin_end"+sfx+".png")).setAttribute("style", "background-color: inherit").setAttribute("class", "hierarchy").setAttribute("alt", "."); @@ -903,17 +981,21 @@ public class HierarchicalTableGenerator { } } } - else - tc.setAttribute("style", "vertical-align: top; text-align : left; "+(c.cellStyle != null && c.cellStyle.contains("background-color") ? "" : "background-color: "+color+"; ")+"border: "+ border +"px #F0F0F0 solid; padding:0px 4px 0px 4px"+(c.cellStyle != null ? ";"+c.cellStyle : "")); + else { + tc.setAttribute("style", "vertical-align: top; text-align : left; "+(c.cellStyle != null && c.cellStyle.contains("background-color") ? "" : "background-color: "+color+"; ")+"border: "+ border +"px #F0F0F0 solid; padding:0px 4px 0px 4px"+(c.cellStyle != null ? ";"+c.cellStyle : "")+lineStyle); + } + if (c.innerTable) { + itc = itr.td(); + } if (!Utilities.noString(icon)) { - XhtmlNode img = tc.addTag("img").setAttribute("alt", "icon").setAttribute("src", srcFor(imagePath, icon)).setAttribute("class", "hierarchy").setAttribute("style", "background-color: "+color+"; background-color: inherit").setAttribute("alt", "."); + XhtmlNode img = itc.addTag("img").setAttribute("alt", "icon").setAttribute("src", srcFor(imagePath, icon)).setAttribute("class", "hierarchy").setAttribute("style", "background-color: "+color+"; background-color: inherit").setAttribute("alt", "."); if (hint != null) img.setAttribute("title", hint); - tc.addText(" "); + itc.addText(" "); } for (Piece p : c.pieces) { if (!Utilities.noString(p.getTag())) { - XhtmlNode tag = tc.addTag(p.getTag()); + XhtmlNode tag = itc.addTag(p.getTag()); if (p.attributes != null) for (String n : p.attributes.keySet()) tag.setAttribute(n, p.attributes.get(n)); @@ -924,7 +1006,7 @@ public class HierarchicalTableGenerator { tag.addChildNodes(p.getChildren()); } } else if (!Utilities.noString(p.getReference())) { - XhtmlNode a = addStyle(tc.addTag("a"), p); + XhtmlNode a = addStyle(itc.addTag("a"), p); a.setAttribute("href", prefixLocalHref(p.getReference())); if (mode == TableGenerationMode.XHTML && suppressExternals) { a.setAttribute("no-external", "true"); @@ -943,25 +1025,25 @@ public class HierarchicalTableGenerator { } if (p.hasChildren()) { - tc.addChildNodes(p.getChildren()); + itc.addChildNodes(p.getChildren()); } } else { if (!Utilities.noString(p.getHint())) { - XhtmlNode s = addStyle(tc.addTag("span"), p); + XhtmlNode s = addStyle(itc.addTag("span"), p); s.setAttribute("title", p.getHint()); s.addText(p.getText()); } else if (p.getStyle() != null) { - XhtmlNode s = addStyle(tc.addTag("span"), p); + XhtmlNode s = addStyle(itc.addTag("span"), p); s.addText(p.getText()); } else { - tc.addText(p.getText()); + itc.addText(p.getText()); } if (p.hasChildren()) { - tc.addChildNodes(p.getChildren()); + itc.addChildNodes(p.getChildren()); } if (p.getTagImg() != null) { - tc.tx(" "); - tc.img(p.getTagImg(), null); + itc.tx(" "); + itc.img(p.getTagImg(), null); } } } @@ -983,6 +1065,15 @@ public class HierarchicalTableGenerator { } private String srcFor(String corePrefix, String filename) throws IOException { + if (!treelines && filename.startsWith("tbl")) { + if (filename.contains("-open")) { + filename = "tbl-open.png"; + } else if (filename.contains("-closed")) { + filename = "tbl-closed.png"; + } else { + filename = "tbl_blank.png"; + } + } if (inLineGraphics) { if (files.containsKey(filename)) return files.get(filename); @@ -991,14 +1082,15 @@ public class HierarchicalTableGenerator { byte[] bytes; File file = ManagedFileAccess.file(Utilities.path(dest, filename)); if (!file.exists()) // because sometime this is called real early before the files exist. it will be built again later because of this - bytes = new byte[0]; + bytes = new byte[0]; else bytes = FileUtils.readFileToByteArray(file); b.append(new String(Base64.encodeBase64(bytes))); -// files.put(filename, b.toString()); + // files.put(filename, b.toString()); return b.toString(); - } else + } else { return corePrefix+filename; + } } public static String help16AsData() throws IOException { @@ -1072,7 +1164,7 @@ public class HierarchicalTableGenerator { b.append(new String(encodeBase64)); files.put(filename, b.toString()); return b.toString(); - } else { + } else if (treelines) { b.append("tbl_bck"); for (Integer i : indents) b.append(Integer.toString(i)); @@ -1098,6 +1190,8 @@ public class HierarchicalTableGenerator { } } return b.toString(); + } else { + return "tbl_bck0.png"; } } @@ -1177,5 +1271,13 @@ public class HierarchicalTableGenerator { } return "#"+uniqueLocalPrefix+"-"+url.substring(1); } + + public boolean isTreelines() { + return treelines; + } + + public void setTreelines(boolean treelines) { + this.treelines = treelines; + } } \ No newline at end of file diff --git a/pom.xml b/pom.xml index cb76f50ff..f9bec3cd9 100644 --- a/pom.xml +++ b/pom.xml @@ -23,7 +23,7 @@ 2.17.0 32.0.1-jre 6.4.1 - 1.7.2 + 1.7.3-SNAPSHOT 2.17.0 5.9.2 1.8.2