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;
017
018 import ca.odell.glazedlists.EventList;
019 import ca.odell.glazedlists.ObservableElementList;
020 import ca.odell.glazedlists.TransformedList;
021 import ca.odell.glazedlists.impl.gui.ThreadProxyEventList;
022 import griffon.plugins.glazedlists.ColumnReader;
023 import griffon.plugins.glazedlists.javafx.gui.DefaultFXTableFormat;
024 import griffon.plugins.glazedlists.javafx.gui.FXTableFormat;
025 import griffon.plugins.glazedlists.javafx.models.DefaultFXTableViewModel;
026 import griffon.plugins.glazedlists.javafx.models.FXTableViewModel;
027 import javafx.application.Platform;
028 import javafx.collections.ObservableList;
029
030 import javax.annotation.Nonnull;
031 import java.util.List;
032
033 import static griffon.util.GriffonClassUtils.requireState;
034 import static java.util.Objects.requireNonNull;
035
036 /**
037 * A factory for creating all sorts of objects to be used with Glazed Lists and JavaFX.
038 *
039 * @author Andres Almriay
040 */
041 public final class GlazedListsJavaFX {
042 private GlazedListsJavaFX() {
043
044 }
045
046 @Nonnull
047 public static <E extends PropertyContainer> ObservableElementList.Connector<E> propertyContainerConnector() {
048 return new PropertyContainerConnector<>();
049 }
050
051 @Nonnull
052 public static <E extends PropertyContainer> ObservableElementList.Connector<E> propertyContainerConnector(@Nonnull String... propertyNames) {
053 return new PropertyContainerConnector<>(propertyNames);
054 }
055
056 /**
057 * Wraps the source in an {@link EventList} that fires all of its update
058 * events from the JavaFX application thread.
059 *
060 * @param source the {@link EventList} to be wrapped. Must not be null.
061 * @return a wrapped {@link EventList} that fires all of its update events inside the JavaFX application thread.
062 */
063 @Nonnull
064 public static <E> TransformedList<E, E> createJavaFXThreadProxyList(@Nonnull EventList<E> source) {
065 return new JavaFXThreadProxyEventList<>(requireNonNull(source, "Argument 'source' must not be null"));
066 }
067
068 /**
069 * Creates a {@link griffon.plugins.glazedlists.javafx.gui.FXTableFormat}.
070 */
071 public static <T> FXTableFormat<T> tableFormat(@Nonnull String[] propertyNames) {
072 return new DefaultFXTableFormat<>(propertyNames);
073 }
074
075 /**
076 * Creates a {@link griffon.plugins.glazedlists.javafx.gui.FXTableFormat}.
077 */
078 public static <T> FXTableFormat<T> tableFormat(@Nonnull String[] propertyNames, @Nonnull String[] columnLabels, @Nonnull ColumnReader[] columnReaders) {
079 return new DefaultFXTableFormat<>(propertyNames, columnLabels, columnReaders);
080 }
081
082 /**
083 * Creates a {@link griffon.plugins.glazedlists.javafx.gui.FXTableFormat}.
084 */
085 public static <T> FXTableFormat<T> tableFormat(@Nonnull FXTableFormat.Options... options) {
086 return new DefaultFXTableFormat<>(options);
087 }
088
089 /**
090 * Creates a {@link griffon.plugins.glazedlists.javafx.gui.FXTableFormat}.
091 */
092 public static <T> FXTableFormat<T> tableFormat(@Nonnull List<FXTableFormat.Options> options) {
093 requireNonNull(options, "Argument 'options' must not be null");
094 requireState(options.size() > 0, "Argument 'options' must not be empty");
095 return new DefaultFXTableFormat<>(options.toArray(new FXTableFormat.Options[options.size()]));
096 }
097
098 /**
099 * Creates a new table model that extracts column data from the given
100 * <code>source</code> using the the given <code>tableFormat</code>.
101 * <p>
102 * <p>The returned table model is <strong>not thread-safe</strong>. Unless otherwise
103 * noted, all methods are only safe to be called from the JavaFX application thread.
104 * To do this programmatically, use {@link javafx.application.Platform#runLater(Runnable)} and
105 * wrap the source list (or some part of the source list's pipeline) using
106 * {@link GlazedListsJavaFX#createJavaFXThreadProxyList(EventList)}.</p>
107 *
108 * @param source the EventList that provides the row objects
109 * @param tableFormat the object responsible for extracting column data
110 * from the row objects
111 */
112 public static <E> FXTableViewModel<E> eventTableViewModel(@Nonnull EventList<E> source, @Nonnull FXTableFormat<? super E> tableFormat) {
113 return eventTableViewModel(new EventObservableList<>(source), tableFormat);
114 }
115
116 /**
117 * Creates a new table model that extracts column data from the given
118 * <code>source</code> using the the given <code>tableFormat</code>.
119 * <p>
120 * <p>The returned table model is <strong>not thread-safe</strong>. Unless otherwise
121 * noted, all methods are only safe to be called from the JavaFX application thread.
122 * To do this programmatically, use {@link javafx.application.Platform#runLater(Runnable)} and
123 * wrap the source list (or some part of the source list's pipeline) using
124 * {@link GlazedListsJavaFX#createJavaFXThreadProxyList(EventList)}.</p>
125 *
126 * @param source the ObservableList that provides the row objects
127 * @param tableFormat the object responsible for extracting column data
128 * from the row objects
129 */
130 public static <E> FXTableViewModel<E> eventTableViewModel(@Nonnull ObservableList<E> source, @Nonnull FXTableFormat<? super E> tableFormat) {
131 return new DefaultFXTableViewModel<>(source, tableFormat);
132 }
133
134 /**
135 * Creates a new table model that extracts column data from the given <code>source</code>
136 * using the the given <code>tableFormat</code>. While holding a read lock,
137 * this method wraps the source list using
138 * {@link GlazedListsJavaFX#createJavaFXThreadProxyList(EventList)}.
139 * <p>
140 * The returned table model is <strong>not thread-safe</strong>. Unless otherwise noted, all
141 * methods are only safe to be called from the event dispatch thread.
142 * </p>
143 *
144 * @param source the EventList that provides the row objects
145 * @param tableFormat the object responsible for extracting column data from the row objects
146 */
147 public static <E> FXTableViewModel<E> eventTableViewModelWithThreadProxyList(@Nonnull EventList<E> source, @Nonnull FXTableFormat<? super E> tableFormat) {
148 EventList<E> proxySource = createJavaFXThreadProxyList(source);
149 return new DefaultFXTableViewModel<>(new EventObservableList<>(proxySource), tableFormat);
150 }
151
152 private static class JavaFXThreadProxyEventList<E> extends ThreadProxyEventList<E> {
153 /**
154 * Create a {@link JavaFXThreadProxyEventList} which delivers changes to the
155 * given <code>source</code> on the JavaFX application thread.
156 *
157 * @param source the {@link EventList} for which to proxy events
158 */
159 private JavaFXThreadProxyEventList(@Nonnull EventList<E> source) {
160 super(source);
161 }
162
163 @Override
164 protected void schedule(Runnable runnable) {
165 requireNonNull(runnable, "Argument 'runnable' must not be null");
166 if (Platform.isFxApplicationThread()) {
167 runnable.run();
168 } else {
169 Platform.runLater(runnable);
170 }
171 }
172 }
173 }
|