001 /*
002 * Copyright 2014-2016 the original author or authors.
003 *
004 * Licensed under the Apache License, Version 2.0 (the "License");
005 * you may not use this file except in compliance with the License.
006 * You may obtain a copy of the License at
007 *
008 * http://www.apache.org/licenses/LICENSE-2.0
009 *
010 * Unless required by applicable law or agreed to in writing, software
011 * distributed under the License is distributed on an "AS IS" BASIS,
012 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
013 * See the License for the specific language governing permissions and
014 * limitations under the License.
015 */
016 package griffon.plugins.glazedlists.javafx.gui;
017
018 import griffon.plugins.glazedlists.ColumnReader;
019 import javafx.beans.value.ObservableValue;
020
021 import javax.annotation.Nonnull;
022 import java.util.List;
023 import java.util.Map;
024
025 import static griffon.util.GriffonClassUtils.requireState;
026 import static griffon.util.GriffonNameUtils.getNaturalName;
027 import static griffon.util.GriffonNameUtils.isBlank;
028 import static java.util.Objects.requireNonNull;
029
030 /**
031 * Defines a read-only {@code FXTableFormat}.
032 *
033 * @author Andres Almiray
034 */
035 public class DefaultFXTableFormat<E> implements FXTableFormat<E> {
036 private static final String ERROR_COLUMN_NAMES_NULL = "Argument 'columnNames' must not be null.";
037
038 protected final String[] columnNames;
039 protected final String[] columnTitles;
040 protected final ColumnReader[] columnReaders;
041 protected final TableCellFactory[] tableCellFactories;
042
043 private static final String NAME = "name";
044 private static final String TITLE = "title";
045 private static final String READER = "reader";
046 private static final String TABLE_CELL_FACTORY = "tableCellFactory";
047
048 public DefaultFXTableFormat(@Nonnull String[] columnNames) {
049 this.columnNames = requireNonNull(columnNames, ERROR_COLUMN_NAMES_NULL);
050 this.columnTitles = new String[columnNames.length];
051 this.columnReaders = new ColumnReader[columnNames.length];
052 this.tableCellFactories = new TableCellFactory[columnNames.length];
053
054 for (int i = 0; i < columnNames.length; i++) {
055 columnTitles[i] = getNaturalName(columnNames[i]);
056 columnReaders[i] = DefaultJavaFXColumnReader.INSTANCE;
057 tableCellFactories[i] = TableCellFactory.DEFAULT_NON_EDITABLE;
058 }
059 }
060
061 public DefaultFXTableFormat(@Nonnull String[] columnNames, @Nonnull String[] columnTitles, @Nonnull ColumnReader[] columnReaders) {
062 this.columnNames = requireNonNull(columnNames, ERROR_COLUMN_NAMES_NULL);
063 this.columnTitles = requireNonNull(columnTitles, "Argument 'columnTitles' must not be null");
064 this.columnReaders = requireNonNull(columnReaders, "Argument 'columnReaders' must not be nul");
065 this.tableCellFactories = new TableCellFactory[columnNames.length];
066
067 requireState(columnNames.length == columnTitles.length,
068 "Arguments 'columNames' and 'columnTitles' have different cardinality. " + columnNames.length + " != " + columnTitles.length);
069 requireState(columnNames.length == columnReaders.length,
070 "Arguments 'columNames' and 'columnReaders' have different cardinality. " + columnNames.length + " != " + columnReaders.length);
071
072 for (int i = 0; i < columnNames.length; i++) {
073 tableCellFactories[i] = TableCellFactory.DEFAULT_NON_EDITABLE;
074 }
075 }
076
077 /**
078 * Creates a {@code FXTableFormat} based on the supplied options.
079 * <p>
080 * Valid option keys are <tt>name</tt>, <tt>title</tt> and <tt>reader</tt>.
081 * </p>
082 *
083 * @param options the options that configure this format
084 */
085 public DefaultFXTableFormat(@Nonnull FXTableFormat.Options... options) {
086 requireNonNull(options, "Argument 'options' must not be null");
087 requireState(options.length > 0, "Argument 'options' must have at least one entry");
088
089 this.columnNames = new String[options.length];
090 this.columnTitles = new String[options.length];
091 this.columnReaders = new ColumnReader[options.length];
092 this.tableCellFactories = new TableCellFactory[options.length];
093
094 int i = 0;
095 for (Options opts : options) {
096 for (Option opt : opts.options) {
097 if (NAME.equalsIgnoreCase(opt.name)) {
098 columnNames[i] = String.valueOf(opt.value);
099 } else if (TITLE.equalsIgnoreCase(opt.name)) {
100 columnTitles[i] = String.valueOf(opt.value);
101 } else if (READER.equalsIgnoreCase(opt.name)) {
102 columnReaders[i] = (ColumnReader) opt.value;
103 } else if (TABLE_CELL_FACTORY.equalsIgnoreCase(opt.name)) {
104 tableCellFactories[i] = (TableCellFactory) opt.value;
105 }
106 }
107
108 if (isBlank(columnNames[i])) {
109 throw new IllegalArgumentException("Column " + i + " must have a value for name:");
110 }
111 if (isBlank(columnTitles[i])) {
112 columnTitles[i] = getNaturalName(columnNames[i]);
113 }
114 if (columnReaders[i] == null) {
115 columnReaders[i] = DefaultJavaFXColumnReader.INSTANCE;
116 }
117
118 i++;
119 }
120 }
121
122 /**
123 * Creates a {@code FXTableFormat} based on the supplied options.
124 * <p>
125 * Valid option keys are <tt>name</tt>, <tt>title</tt> and <tt>reader</tt>.
126 * </p>
127 *
128 * @param options the options that configure this format
129 */
130 public DefaultFXTableFormat(@Nonnull List<Map<String, Object>> options) {
131 requireNonNull(options, "Argument 'options' must not be null");
132 requireState(options.size() > 0, "Argument 'options' must have at least one entry");
133
134 this.columnNames = new String[options.size()];
135 this.columnTitles = new String[options.size()];
136 this.columnReaders = new ColumnReader[options.size()];
137 this.tableCellFactories = new TableCellFactory[options.size()];
138
139 int i = 0;
140 for (Map<String, Object> op : options) {
141 if (op.containsKey(NAME)) {
142 columnNames[i] = String.valueOf(op.get(NAME));
143 }
144 if (isBlank(columnNames[i])) {
145 throw new IllegalArgumentException("Column " + i + " must have a value for name:");
146 }
147
148 if (op.containsKey(TITLE)) {
149 columnTitles[i] = String.valueOf(op.get(TITLE));
150 } else {
151 columnTitles[i] = getNaturalName(columnNames[i]);
152 }
153
154 if (op.containsKey(READER) && op.get(READER) instanceof ColumnReader) {
155 columnReaders[i] = (ColumnReader) op.get(READER);
156 } else {
157 columnReaders[i] = DefaultJavaFXColumnReader.INSTANCE;
158 }
159
160 if (op.containsKey(TABLE_CELL_FACTORY) && op.get(TABLE_CELL_FACTORY) instanceof TableCellFactory) {
161 tableCellFactories[i] = (TableCellFactory) op.get(TABLE_CELL_FACTORY);
162 } else {
163 tableCellFactories[i] = TableCellFactory.DEFAULT_EDITABLE;
164 }
165
166 i++;
167 }
168 }
169
170 @Override
171 public int getColumnCount() {
172 return columnNames.length;
173 }
174
175 @Override
176 public String getColumnName(int column) {
177 return columnTitles[column];
178 }
179
180 @Override
181 @SuppressWarnings("unchecked")
182 public Object getColumnValue(E baseObject, int column) {
183 return columnReaders[column].getValue(baseObject, columnNames[column], column);
184 }
185
186 @Override
187 @SuppressWarnings("unchecked")
188 public ObservableValue<?> getColumnObservableValue(E baseObject, int column) {
189 return (ObservableValue<?>) columnReaders[column].getValue(baseObject, columnNames[column], column);
190 }
191
192 @Nonnull
193 @Override
194 public TableCellFactory getTableCellFactory(int column) {
195 return tableCellFactories[column];
196 }
197 }
|