001/* 002 * Copyright (c) 2017, 2022, Oracle and/or its affiliates. All rights reserved. 003 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 004 * 005 * This code is free software; you can redistribute it and/or modify it 006 * under the terms of the GNU General Public License version 2 only, as 007 * published by the Free Software Foundation. Oracle designates this 008 * particular file as subject to the "Classpath" exception as provided 009 * by Oracle in the LICENSE file that accompanied this code. 010 * 011 * This code is distributed in the hope that it will be useful, but WITHOUT 012 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 013 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 014 * version 2 for more details (a copy is included in the LICENSE file that 015 * accompanied this code). 016 * 017 * You should have received a copy of the GNU General Public License version 018 * 2 along with this work; if not, write to the Free Software Foundation, 019 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 020 * 021 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 022 * or visit www.oracle.com if you need additional information or have any 023 * questions. 024 */ 025 026package org.jdrupes.mdoclet.internal.doclets.formats.html; 027 028import java.io.IOException; 029import java.io.Writer; 030import java.util.Arrays; 031import java.util.List; 032 033import org.jdrupes.mdoclet.internal.doclets.formats.html.markup.ContentBuilder; 034import org.jdrupes.mdoclet.internal.doclets.formats.html.markup.HtmlAttr; 035import org.jdrupes.mdoclet.internal.doclets.formats.html.markup.HtmlStyle; 036import org.jdrupes.mdoclet.internal.doclets.formats.html.markup.HtmlTree; 037import org.jdrupes.mdoclet.internal.doclets.toolkit.Content; 038 039/** 040 * A row of header cells for an HTML table. 041 * 042 * The header contains a list of {@code <th>} cells, providing the column headers. 043 * The attribute {@code scope="col"} is automatically added to each header cell. 044 * In addition, a series of style class names can be specified, to be applied one per cell. 045 */ 046public class TableHeader extends Content { 047 048 /** 049 * The content to be put in each of the {@code <th>} cells in the header row. 050 */ 051 private final List<Content> cellContents; 052 /** 053 * The style class names for each of the {@code <th>} cells in the header row. 054 * If not set, default style names will be used. 055 */ 056 private List<HtmlStyle> styles; 057 058 private boolean[] sortable; 059 060 /** 061 * Creates a header row, with localized content for each cell. 062 * Resources keys will be converted to content using {@link Contents#getContent(String)}. 063 * @param contents a factory to get the content for each header cell. 064 * @param colHeaderKeys the resource keys for the content in each cell. 065 */ 066 public TableHeader(Contents contents, String... colHeaderKeys) { 067 this.cellContents = Arrays.stream(colHeaderKeys) 068 .map(contents::getContent) 069 .toList(); 070 } 071 072 /** 073 * Creates a header row, with specified content for each cell. 074 * @param headerCellContents a content object for each header cell 075 */ 076 public TableHeader(Content... headerCellContents) { 077 this.cellContents = Arrays.asList(headerCellContents); 078 } 079 080 /** 081 * Creates a header row, with specified content for each cell. 082 * @param headerCellContents a content object for each header cell 083 */ 084 public TableHeader(List<Content> headerCellContents) { 085 this.cellContents = headerCellContents; 086 } 087 088 /** 089 * Set the style class names for each header cell. 090 * The number of names must match the number of cells given to the constructor. 091 * @param styles the style class names 092 * @return this object 093 */ 094 public TableHeader styles(HtmlStyle... styles) { 095 if (styles.length != cellContents.size()) { 096 throw new IllegalStateException(); 097 } 098 this.styles = Arrays.asList(styles); 099 return this; 100 } 101 102 /** 103 * Makes the table sortable by the content of columns for which the 104 * argument boolean array contains {@code true}. 105 * @param sortable boolean array specifying sortable columns 106 * @return this object 107 */ 108 public TableHeader sortable(boolean... sortable) { 109 if (sortable.length != cellContents.size()) { 110 throw new IllegalStateException(); 111 } 112 this.sortable = sortable; 113 return this; 114 } 115 116 /** 117 * Set the style class names for each header cell. 118 * The number of names must match the number of cells given to the constructor. 119 * @param styles the style class names 120 * @return this object 121 */ 122 public TableHeader styles(List<HtmlStyle> styles) { 123 if (styles.size() != cellContents.size()) { 124 throw new IllegalStateException(); 125 } 126 this.styles = styles; 127 return this; 128 } 129 130 /** 131 * {@inheritDoc} 132 * 133 * @implSpec This implementation always returns {@code false}. 134 * 135 * @return {@code false} 136 */ 137 @Override 138 public boolean isEmpty() { 139 return false; 140 } 141 142 @Override 143 public boolean write(Writer out, String newline, boolean atNewline) 144 throws IOException { 145 return toContent().write(out, newline, atNewline); 146 } 147 148 /** 149 * Converts this header to a {@link Content} object, for use in an {@link HtmlTree}. 150 * @return a Content object 151 */ 152 private Content toContent() { 153 Content header = new ContentBuilder(); 154 int i = 0; 155 for (Content cellContent : cellContents) { 156 HtmlStyle style = (styles != null) ? styles.get(i) 157 : (i == 0) ? HtmlStyle.colFirst 158 : (i == (cellContents.size() - 1)) ? HtmlStyle.colLast 159 : (i == 1) ? HtmlStyle.colSecond : null; 160 var cell = HtmlTree.DIV(HtmlStyle.tableHeader, cellContent); 161 if (style != null) { 162 cell.addStyle(style); 163 } 164 if (sortable != null && sortable[i]) { 165 cell.put(HtmlAttr.ONCLICK, 166 "sortTable(this, " + i + ", " + sortable.length + ")"); 167 // Current tables happen to be sorted by first column by 168 // default, this may not hold true for future uses. 169 if (i == 0) { 170 cell.addStyle("sort-asc"); 171 } 172 } 173 header.add(cell); 174 i++; 175 } 176 return header; 177 } 178 179}