javafx - Provide different TreeCell conditionally in CellFactory -


i have treeview in cells must display different information according real implementation of treeitem's value.

my domain model looks like:

domain model

it seemed natural me split behaviour of "how display task in cell" or "how display group in cell" in 2 different classes.

public abstract class componenttreecell<t extends component> extends treecell<t> {     @override     protected void updateitem(t item, boolean empty)     {         //some common logic...     } }  public class grouptreecell extends componenttreecell<group> {     @override     protected void updateitem(group item, boolean empty)     {         super.updateitem(item, empty);          //some group-specific-logic     }     }  public class tasktreecell extends componenttreecell<task> {     @override     protected void updateitem(task item, boolean empty)     {         super.updateitem(item, empty);          //some task-specific-logic     }     } 

the following controller class contains treeview set cellfactory.

public class controller implements initializable {     @fxml     private treeview<component> treeview;      @override     public void initialize(url url, resourcebundle bundle)     {         treeview.setcellfactory(new callback<treeview<component>, treecell<component>>()         {             @override             public treecell<component> call(treeview<component> arg0)             {                 if(/* stuck */ instanceof group)                 {                     return new grouptreecell();                 }                 else if(/* stuck */ instanceof task)                 {                     return new tasktreecell();                 }                 else                 {                     return new defaulttreecell();                 }             }         });     } } 

but here stuck @ moment decide kind of cell have return. indeed have in parameter related treeview , not related treeitem !

it seems me kind of weakness of javafx. why javafx gives full treeview user when need retrieve 1 treecell ??

is there way in manner or have implement 2 different behaviour in same custom treecell implementation ?

public class componenttreecell extends treecell<component> {         @override         protected void updateitem(component item, boolean empty)         {             //some common logic...              if(item instanceof group)             {                 //group-specific logic...             }             else if(item instanceof task)             {                 //task-specific logic...             }             else             {                 //default logic...             }        } } 

why javafx gives full treeview user when need retrieve 1 treecell ??

because there isn't 1-1 relationship between treeitems , treecells: treeview create small number of treecells (even if tree has large number of items). treecells reused display different treeitems, example if nodes expanded/collapsed, or if user scrolls.

it done way performance. actual cells provide rendering quite large objects: ui components , carry css styling etc them. actual data displayed, i.e. treeitems relatively lightweight; simple wrappers strings. mechanism allows have treeviews huge amounts of data not impose huge burden on performance. creating treecell every treeitem not allow this.

because of this, treecell provide factory has able handle treeitem might given treeview. example, user changes items displayed (by expanding/collapsing or scrolling), treecell instance displaying task might used display group. purpose of updateitem(...) method; called when treecell reused.

this means setup won't work. need treecell<component> implementation in last code example. of course factor configuration separate classes if like, like:

public class componenttreecell extends treecell<component> {     @override     protected void updateitem(component item, boolean empty)     {         super.updateitem(item, empty);         cellconfiguratorfactory.getconfigurator(item).configure(this, item, empty);     }  } 

factory:

public class cellconfiguratorfactory {      private static cellconfigurator<task> taskcellconfigurator ;     private static cellconfigurator<group> groupcellconfigurator ;     private static cellconfigurator<component> defaultcellconfigurator ;      private static cellconfigurator getconfigurator(component item) {         if (item instanceof task) {             if (taskcellconfigurator == null) {                 taskcellconfigurator = new taskcellconfigurator();             }             return taskcellconfigurator ;         } else if (item instanceof group) {             if (groupcellconfigurator == null) {                 groupcellconfigurator = new groupcellconfigurator();             }             return groupcellconfigurator ;         } else {             if (defaultcellconfigurator == null) {                 defaultcellconfigurator = new defaultcellconfigurator();             }             return defaultcellconfigurator ;         }     } } 

(note can afford assume factory ever used single thread, since happen on fx application thread.)

and

public interface cellconfigurator<t extends component> {     public void configurecell(componenttreecell cell, t item, boolean empty); } 

with, example,

public class taskcellconfigurator implements cellconfigurator<task> {     public void configurecell(treecell<component> cell, task item, boolean empty) {         // task-specific implementation...     } } 

however, i'm not sure additional structure worth effort here.


Comments