44 import javafx.animation.Timeline;
45 import javafx.beans.InvalidationListener;
46 import javafx.beans.Observable;
47 import javafx.beans.binding.DoubleBinding;
48 import javafx.beans.property.SimpleDoubleProperty;
49 import javafx.beans.value.ChangeListener;
50 import javafx.beans.value.ObservableValue;
51 import javafx.collections.ObservableList;
52 import javafx.event.ActionEvent;
53 import javafx.event.Event;
54 import javafx.event.EventHandler;
55 import javafx.geometry.HPos;
56 import javafx.geometry.Orientation;
57 import javafx.geometry.VPos;
58 import javafx.scene.Node;
59 import javafx.scene.control.ContentDisplay;
60 import javafx.scene.control.Label;
61 import javafx.scene.control.ListCell;
62 import javafx.scene.control.ListView;
63 import javafx.scene.control.Skin;
64 import javafx.scene.image.Image;
65 import javafx.scene.image.ImageView;
66 import javafx.scene.input.MouseEvent;
67 import javafx.scene.layout.ColumnConstraints;
68 import javafx.scene.layout.GridPane;
69 import javafx.scene.layout.Priority;
70 import javafx.scene.layout.Region;
71 import javafx.scene.layout.VBox;
72 import javafx.scene.paint.Color;
73 import javafx.scene.shape.Rectangle;
74 import javafx.scene.text.Text;
75 import javafx.stage.Window;
76 import javafx.util.Callback;
77 import javafx.util.Duration;
78 import com.javafx.experiments.scheduleapp.TouchClickedEventAvoider;
79 import com.javafx.experiments.scheduleapp.Page;
80 import com.javafx.experiments.scheduleapp.control.EventPopoverPage;
81 import com.javafx.experiments.scheduleapp.control.Popover;
82 import com.javafx.experiments.scheduleapp.control.ResizableWrappingText;
83 import com.javafx.experiments.scheduleapp.control.SearchBox;
84 import com.javafx.experiments.scheduleapp.data.DataService;
85 import com.javafx.experiments.scheduleapp.model.Session;
86 import com.javafx.experiments.scheduleapp.model.SessionTime;
87 import com.javafx.experiments.scheduleapp.model.Speaker;
88 import com.sun.javafx.scene.control.skin.FXVK;
89
90 import static com.javafx.experiments.scheduleapp.ConferenceScheduleApp.*;
91 import static com.javafx.experiments.scheduleapp.Theme.*;
92 import java.awt.image.BufferedImage;
93 import java.io.IOException;
94 import java.net.URL;
95 import java.util.HashMap;
96 import java.util.Map;
97 import java.util.logging.Level;
98 import java.util.logging.Logger;
99 import javafx.embed.swing.SwingFXUtils;
100 import javafx.scene.image.WritableImage;
101 import javax.imageio.ImageIO;
102
103 /**
104 * Page showing searchable list of all speakers at the conference
105 */
106 public class SpeakersPage extends Page implements ChangeListener<String> {
107 private static DateFormat DATE_TIME_FORMAT = new SimpleDateFormat("hh:mma EEE");
108 private static final Pattern HYPERLINK_PATTERN = Pattern.compile("http(s)?://\\S+");
109 private static final int PIC_SIZE = 48;
110 private static final int GAP = 6;
111 private static final int IMG_GAP = 12;
112 private static final int MIN_HEIGHT = GAP + PIC_SIZE + 10 + GAP;
113 private static final int TEXT_LEFT = GAP+PIC_SIZE+IMG_GAP;
114
115 private final SpeakerList speakersList = new SpeakerList();
116 private final SearchBox searchBox = new SearchBox();
117 private final Map<Speaker,Image> speakerImageCache = new HashMap<>();
118
119 /**
120 * index of currently expanded cell. We need to keep tack of the cell that
121 * is expanded so that when you scroll away from it and its cell is reused
245 * @param show true if the star should be added to the label, false if it
246 * should be removed.
247 */
248 private static void updateStar(Label sessionTitle, boolean show) {
249 if(show) {
250 ImageView star = new ImageView(STAR);
251 sessionTitle.setGraphic(star);
252 sessionTitle.setContentDisplay(ContentDisplay.RIGHT);
253 } else {
254 sessionTitle.setGraphic(null);
255 }
256 }
257
258 /**
259 * Custom list for speakers, will all standard CSS removed an using our
260 * custom SpeakerListCell.
261 */
262 private class SpeakerList extends ListView<Speaker> implements Callback<ListView<Speaker>, ListCell<Speaker>>{
263 public SpeakerList(){
264 getStyleClass().setAll("twitter-list-view");
265 // skinClassNameProperty().set("com.sun.javafx.scene.control.skin.ListViewSkin");
266 setSkin(new com.sun.javafx.scene.control.skin.ListViewSkin(this));
267 setCellFactory(this);
268 // hack workaround for cell sizing
269 Node node = lookup(".clipped-container");
270 if (node != null) node.setManaged(true);
271 }
272
273 @Override public ListCell<Speaker> call(ListView<Speaker> p) {
274 return new SpeakerListCell();
275 }
276 }
277
278 /**
279 * The main body of the speaker list cell. This is separate from the cell
280 * so that it can be cached and not need to be updated while the cells clip
281 * is changing during expansion.
282 */
283 private final static class SpeakerListCellBody extends Region {
284 private final Text name = new Text();
285 private final Text company = new Text();
286 private final ImageView image = new ImageView();
|
44 import javafx.animation.Timeline;
45 import javafx.beans.InvalidationListener;
46 import javafx.beans.Observable;
47 import javafx.beans.binding.DoubleBinding;
48 import javafx.beans.property.SimpleDoubleProperty;
49 import javafx.beans.value.ChangeListener;
50 import javafx.beans.value.ObservableValue;
51 import javafx.collections.ObservableList;
52 import javafx.event.ActionEvent;
53 import javafx.event.Event;
54 import javafx.event.EventHandler;
55 import javafx.geometry.HPos;
56 import javafx.geometry.Orientation;
57 import javafx.geometry.VPos;
58 import javafx.scene.Node;
59 import javafx.scene.control.ContentDisplay;
60 import javafx.scene.control.Label;
61 import javafx.scene.control.ListCell;
62 import javafx.scene.control.ListView;
63 import javafx.scene.control.Skin;
64 import javafx.scene.control.skin.ListViewSkin;
65 import javafx.scene.image.Image;
66 import javafx.scene.image.ImageView;
67 import javafx.scene.input.MouseEvent;
68 import javafx.scene.layout.ColumnConstraints;
69 import javafx.scene.layout.GridPane;
70 import javafx.scene.layout.Priority;
71 import javafx.scene.layout.Region;
72 import javafx.scene.layout.VBox;
73 import javafx.scene.paint.Color;
74 import javafx.scene.shape.Rectangle;
75 import javafx.scene.text.Text;
76 import javafx.stage.Window;
77 import javafx.util.Callback;
78 import javafx.util.Duration;
79 import com.javafx.experiments.scheduleapp.TouchClickedEventAvoider;
80 import com.javafx.experiments.scheduleapp.Page;
81 import com.javafx.experiments.scheduleapp.control.EventPopoverPage;
82 import com.javafx.experiments.scheduleapp.control.Popover;
83 import com.javafx.experiments.scheduleapp.control.ResizableWrappingText;
84 import com.javafx.experiments.scheduleapp.control.SearchBox;
85 import com.javafx.experiments.scheduleapp.data.DataService;
86 import com.javafx.experiments.scheduleapp.model.Session;
87 import com.javafx.experiments.scheduleapp.model.SessionTime;
88 import com.javafx.experiments.scheduleapp.model.Speaker;
89 import com.sun.javafx.scene.control.skin.FXVK;
90
91 import static com.javafx.experiments.scheduleapp.ConferenceScheduleApp.*;
92 import static com.javafx.experiments.scheduleapp.Theme.*;
93
94 import java.util.HashMap;
95 import java.util.Map;
96
97 /**
98 * Page showing searchable list of all speakers at the conference
99 */
100 public class SpeakersPage extends Page implements ChangeListener<String> {
101 private static DateFormat DATE_TIME_FORMAT = new SimpleDateFormat("hh:mma EEE");
102 private static final Pattern HYPERLINK_PATTERN = Pattern.compile("http(s)?://\\S+");
103 private static final int PIC_SIZE = 48;
104 private static final int GAP = 6;
105 private static final int IMG_GAP = 12;
106 private static final int MIN_HEIGHT = GAP + PIC_SIZE + 10 + GAP;
107 private static final int TEXT_LEFT = GAP+PIC_SIZE+IMG_GAP;
108
109 private final SpeakerList speakersList = new SpeakerList();
110 private final SearchBox searchBox = new SearchBox();
111 private final Map<Speaker,Image> speakerImageCache = new HashMap<>();
112
113 /**
114 * index of currently expanded cell. We need to keep tack of the cell that
115 * is expanded so that when you scroll away from it and its cell is reused
239 * @param show true if the star should be added to the label, false if it
240 * should be removed.
241 */
242 private static void updateStar(Label sessionTitle, boolean show) {
243 if(show) {
244 ImageView star = new ImageView(STAR);
245 sessionTitle.setGraphic(star);
246 sessionTitle.setContentDisplay(ContentDisplay.RIGHT);
247 } else {
248 sessionTitle.setGraphic(null);
249 }
250 }
251
252 /**
253 * Custom list for speakers, will all standard CSS removed an using our
254 * custom SpeakerListCell.
255 */
256 private class SpeakerList extends ListView<Speaker> implements Callback<ListView<Speaker>, ListCell<Speaker>>{
257 public SpeakerList(){
258 getStyleClass().setAll("twitter-list-view");
259 // skinClassNameProperty().set("javafx.scene.control.skin.ListViewSkin");
260 setSkin(new ListViewSkin(this));
261 setCellFactory(this);
262 // hack workaround for cell sizing
263 Node node = lookup(".clipped-container");
264 if (node != null) node.setManaged(true);
265 }
266
267 @Override public ListCell<Speaker> call(ListView<Speaker> p) {
268 return new SpeakerListCell();
269 }
270 }
271
272 /**
273 * The main body of the speaker list cell. This is separate from the cell
274 * so that it can be cached and not need to be updated while the cells clip
275 * is changing during expansion.
276 */
277 private final static class SpeakerListCellBody extends Region {
278 private final Text name = new Text();
279 private final Text company = new Text();
280 private final ImageView image = new ImageView();
|