Skip to content

Commit 8581da1

Browse files
committed
UI/UX: Create expandable list view component
1 parent caa5b55 commit 8581da1

File tree

2 files changed

+160
-0
lines changed

2 files changed

+160
-0
lines changed
Lines changed: 145 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,145 @@
1+
package root.javafx.CustomView;
2+
3+
import java.util.HashSet;
4+
import java.util.Set;
5+
6+
import de.jensd.fx.glyphs.fontawesome.FontAwesomeIcon;
7+
import de.jensd.fx.glyphs.fontawesome.FontAwesomeIconView;
8+
import javafx.collections.ObservableList;
9+
import javafx.event.EventHandler;
10+
import javafx.scene.control.ListCell;
11+
import javafx.scene.control.ListView;
12+
import javafx.scene.control.TitledPane;
13+
import javafx.scene.input.MouseEvent;
14+
import javafx.scene.layout.BorderPane;
15+
import javafx.scene.paint.Paint;
16+
import javafx.scene.text.Text;
17+
import javafx.util.Callback;
18+
19+
public class ExpandableListView<E> extends ListView<E> {
20+
21+
private ContentProvider<E> contentProvider = new ContentProvider<E>() {
22+
@Override
23+
public String getTitleOf(final E item) {
24+
return item.toString();
25+
}
26+
27+
@Override
28+
public String getContentOf(final E item) {
29+
return getTitleOf(item);
30+
}
31+
};
32+
33+
private final Set<E> expandedItems = new HashSet<E>();
34+
35+
public ExpandableListView(FontAwesomeIcon icon, Paint iconColor) {
36+
setSelectionModel(null);
37+
setCellFactory(new Callback<ListView<E>, ListCell<E>>() {
38+
@Override
39+
public ListCell<E> call(final ListView<E> param) {
40+
final TitledPane titledPane = new TitledPane();
41+
final Text contentArea = new Text();
42+
final FontAwesomeIconView iconView = new FontAwesomeIconView(icon);
43+
iconView.setFill(Paint.valueOf("#183279"));
44+
45+
titledPane.setAnimated(false);
46+
titledPane.setCollapsible(true);
47+
titledPane.setExpanded(false);
48+
titledPane.setGraphic(iconView);
49+
titledPane.setContent(contentArea);
50+
51+
final BorderPane contentAreaWrapper = new BorderPane();
52+
contentAreaWrapper.setLeft(contentArea);
53+
titledPane.setContent(contentAreaWrapper);
54+
55+
titledPane.addEventHandler(MouseEvent.MOUSE_CLICKED, new EventHandler<MouseEvent>() {
56+
@SuppressWarnings("unchecked")
57+
@Override
58+
public void handle(final MouseEvent event) {
59+
final boolean expanded = titledPane.isExpanded();
60+
final E item = (E) titledPane.getUserData();
61+
if (item == null) {
62+
return;
63+
}
64+
if (expanded) {
65+
expandedItems.add(item);
66+
} else {
67+
expandedItems.remove(item);
68+
}
69+
}
70+
});
71+
72+
return new ListCell<E>() {
73+
@Override
74+
protected void updateItem(final E item, final boolean empty) {
75+
super.updateItem(item, empty);
76+
if (empty) {
77+
titledPane.setText("");
78+
contentArea.setText("");
79+
return;
80+
}
81+
final boolean expanded = isExpanded(item);
82+
titledPane.setUserData(item);
83+
titledPane.setExpanded(expanded);
84+
titledPane.setText(contentProvider.getTitleOf(item));
85+
contentArea.setText(contentProvider.getContentOf(item));
86+
setGraphic(titledPane);
87+
}
88+
};
89+
}
90+
});
91+
getStyleClass().addAll("expandable-listview", "gray-scrollbar");
92+
}
93+
94+
public void setContentProvider(final ContentProvider<E> contentProvider) {
95+
this.contentProvider = contentProvider;
96+
}
97+
98+
public void expand(E item) {
99+
expand(item, true);
100+
}
101+
102+
public void collapse(E item) {
103+
expand(item, false);
104+
}
105+
106+
private void expand(E item, boolean expand) {
107+
if (expand) {
108+
this.expandedItems.add(item);
109+
} else {
110+
this.expandedItems.remove(item);
111+
}
112+
113+
ObservableList<E> o = getItems();
114+
setItems(null);
115+
setItems(o);
116+
}
117+
118+
public boolean isExpanded(E item) {
119+
return this.expandedItems.contains(item);
120+
}
121+
122+
public static interface ContentProvider<E> {
123+
String getTitleOf(E item);
124+
125+
String getContentOf(E item);
126+
}
127+
128+
public static class Item {
129+
String title;
130+
String content;
131+
132+
public Item(String title, String content) {
133+
this.title = title;
134+
this.content = content;
135+
}
136+
137+
public String getTitle() {
138+
return title;
139+
}
140+
141+
public String getContent() {
142+
return content;
143+
}
144+
}
145+
}

src/main/resources/css/javaFx.css

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -279,3 +279,18 @@
279279
-fx-pref-height: 0;
280280
-fx-max-height: 0;
281281
}
282+
283+
/* Expandable listview */
284+
.expandable-listview .list-cell {
285+
-fx-padding: 0;
286+
-fx-background-color: white;
287+
}
288+
289+
.expandable-listview .titled-pane:focused {
290+
-fx-text-fill: black;
291+
}
292+
293+
.expandable-listview .titled-pane > .title {
294+
-fx-background-color: -fx-box-border, -fx-inner-border, white;
295+
-fx-padding: 7 5 7 5;
296+
}

0 commit comments

Comments
 (0)