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+ }
0 commit comments