7bdc81598984329854855f21507cce8f03db611a
[taxeditor.git] / eu.etaxonomy.taxeditor.store / src / main / java / eu / etaxonomy / taxeditor / preference / wizard / CheckBoxTreeComposite.java
1 /**
2 * Copyright (C) 2018 EDIT
3 * European Distributed Institute of Taxonomy
4 * http://www.e-taxonomy.eu
5 *
6 * The contents of this file are subject to the Mozilla Public License Version 1.1
7 * See LICENSE.TXT at the top of this package for the full license terms.
8 */
9 package eu.etaxonomy.taxeditor.preference.wizard;
10
11 import java.util.Arrays;
12 import java.util.List;
13
14 import org.eclipse.jface.resource.JFaceResources;
15 import org.eclipse.jface.viewers.AbstractTreeViewer;
16 import org.eclipse.jface.viewers.CheckboxTreeViewer;
17 import org.eclipse.jface.viewers.IBaseLabelProvider;
18 import org.eclipse.jface.viewers.ITreeContentProvider;
19 import org.eclipse.jface.viewers.ITreeSelection;
20 import org.eclipse.swt.SWT;
21 import org.eclipse.swt.events.SelectionEvent;
22 import org.eclipse.swt.events.SelectionListener;
23 import org.eclipse.swt.graphics.Font;
24 import org.eclipse.swt.layout.GridData;
25 import org.eclipse.swt.layout.GridLayout;
26 import org.eclipse.swt.widgets.Button;
27 import org.eclipse.swt.widgets.Composite;
28 import org.eclipse.swt.widgets.Tree;
29 import org.eclipse.swt.widgets.TreeItem;
30 import org.eclipse.swt.widgets.Widget;
31
32 import eu.etaxonomy.taxeditor.l10n.Messages;
33 import eu.etaxonomy.taxeditor.model.ImageResources;
34
35 /**
36 * @author pplitzner
37 * @since Oct 26, 2018
38 *
39 */
40 public class CheckBoxTreeComposite extends Composite implements SelectionListener {
41
42 private static final Font FONT_DEFAULT = JFaceResources.getFontRegistry().get(JFaceResources.DEFAULT_FONT);
43 private static final Font FONT_ITALIC = JFaceResources.getFontRegistry().getItalic(JFaceResources.DEFAULT_FONT);
44 private static final Font FONT_BOLD = JFaceResources.getFontRegistry().getBold(JFaceResources.DEFAULT_FONT);
45 private CheckboxTreeViewer viewer;
46 private Button btnCollapse;
47 private Button btnExpand;
48 private Button btnSelectAllChildren;
49 private Button btnSelectDirectChildren;
50
51 protected Object[] checkedElements;
52
53 private boolean allowTopLevelSelection = false;
54
55 public CheckBoxTreeComposite(Composite parent, ITreeContentProvider contentProvider, IBaseLabelProvider labelProvider, int style) {
56 super(parent, style);
57 GridLayout layout = new GridLayout();
58 layout.marginHeight = 0;
59 setLayout(layout);
60
61 Composite toolbar = new Composite(this, SWT.NONE);
62 toolbar.setLayoutData(new GridData(SWT.RIGHT, SWT.CENTER, true, false, 1, 1));
63 GridLayout gl_toolbar = new GridLayout(4, false);
64 gl_toolbar.horizontalSpacing = 4;
65 gl_toolbar.marginHeight = 0;
66 gl_toolbar.verticalSpacing = 0;
67 toolbar.setLayout(gl_toolbar);
68
69 btnCollapse = new Button(toolbar, SWT.NONE);
70 btnCollapse.addSelectionListener(this);
71 btnCollapse.setImage(ImageResources.getImage(ImageResources.COLLAPSE_ALL));
72 btnCollapse.setToolTipText(""); //$NON-NLS-1$
73
74 btnExpand = new Button(toolbar, SWT.NONE);
75 btnExpand.addSelectionListener(this);
76 btnExpand.setImage(ImageResources.getImage(ImageResources.EXPAND));
77 btnExpand.setToolTipText(""); //$NON-NLS-1$
78
79 btnSelectDirectChildren = new Button(toolbar, SWT.NONE);
80 btnSelectDirectChildren.addSelectionListener(this);
81 btnSelectDirectChildren.setImage(ImageResources.getImage(ImageResources.FLAT));
82 btnSelectDirectChildren.setToolTipText(Messages.CheckBoxTreeComposite_SELECT_DIRECT_CHILDREN);
83
84 btnSelectAllChildren = new Button(toolbar, SWT.NONE);
85 btnSelectAllChildren.addSelectionListener(this);
86 btnSelectAllChildren.setImage(ImageResources.getImage(ImageResources.HIERARCHICAL));
87 btnSelectAllChildren.setToolTipText(""); //$NON-NLS-1$
88
89 Tree tree = new Tree(this, SWT.BORDER | SWT.CHECK);
90 tree.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true));
91 tree.addListener(SWT.Selection, event -> {
92 if (event.detail == SWT.CHECK) {
93 TreeItem item = (TreeItem) event.item;
94 if(!allowTopLevelSelection && item.getParentItem()==null){
95 // top level selection not allowed
96 item.setChecked(false);
97 return;
98 }
99
100 if (item.getChecked()){
101 if (checkedElements != null){
102 Object[] tempArray = Arrays.copyOf(checkedElements, checkedElements.length +1);
103 tempArray[checkedElements.length] = item.getData();
104 checkedElements = tempArray;
105 }
106
107 }else{
108 int index = 0;
109 if (checkedElements != null){
110 for (Object o:checkedElements){
111 if (o != null && o.equals(item.getData())){
112 break;
113 }
114 index ++;
115 }
116 checkedElements[index] = null;
117 }
118 }
119
120 updateItem(item);
121 }
122 });
123
124 viewer = new CdmCheckBoxTreeViewer(tree);
125 viewer.setContentProvider(contentProvider);
126 viewer.setLabelProvider(labelProvider);
127
128 }
129
130
131 private void updateItem(TreeItem treeItem){
132 TreeItem parentItem = treeItem.getParentItem();
133 if(parentItem!=null){
134 updateItem(parentItem);
135 }
136 else{
137 updateChildItems(treeItem);
138 }
139 }
140
141 private void updateChildItems(TreeItem treeItem){
142 treeItem.setFont(FONT_DEFAULT);
143 TreeItem[] children = treeItem.getItems();
144 if(children.length==0){
145 return;
146 }
147 int checkedCount = 0;
148 for (TreeItem child : children) {
149 updateChildItems(child);
150
151 if(child.getChecked() ){
152 if ((child.getFont().equals(FONT_BOLD)) || (child.getItems().length == 0)) {
153 checkedCount++;
154 }
155 //some children are checked
156 treeItem.setFont(FONT_ITALIC);
157 }
158 else if(child.getFont().equals(FONT_ITALIC)
159 || child.getFont().equals(FONT_BOLD)){
160 //some children are checked
161 treeItem.setFont(FONT_ITALIC);
162 }
163 }
164 if(checkedCount==children.length){
165 //all children are checked
166 treeItem.setFont(FONT_BOLD);
167 }
168 else if(!treeItem.getFont().equals(FONT_ITALIC)){
169 if(checkedCount>0){
170 //some children are checked
171 treeItem.setFont(FONT_ITALIC);
172 }
173 else{
174 //no children are checked
175 treeItem.setFont(FONT_DEFAULT);
176 }
177 }
178 }
179
180
181 public CheckboxTreeViewer getViewer() {
182 return viewer;
183 }
184
185 public void setAllowTopLevelSelection(boolean allowTopLevelSelection) {
186 this.allowTopLevelSelection = allowTopLevelSelection;
187 }
188
189 /**
190 * Checks the tree items corresponding to the given elements.<br>
191 * @param elements
192 */
193 public void setCheckedElements(Object[] elements) {
194
195 this.checkedElements = elements;
196 viewer.setCheckedElements(elements);
197 for (Object element: checkedElements) {
198 viewer.reveal(element);
199 }
200 TreeItem[] rootItems = viewer.getTree().getItems();
201 for (TreeItem rootItem : rootItems) {
202 updateItem(rootItem);
203 }
204
205 }
206
207 /**
208 * Grays the tree items corresponding to the given elements.<br>
209 * @param elements
210 */
211 public void setGrayedElements(Object[] elements) {
212 viewer.setGrayedElements(elements);
213 for (Object element: elements) {
214 viewer.reveal(element);
215 }
216 TreeItem[] rootItems = viewer.getTree().getItems();
217 for (TreeItem rootItem : rootItems) {
218 updateItem(rootItem);
219 }
220
221 }
222
223 @Override
224 public void widgetSelected(SelectionEvent e) {
225 ITreeSelection structuredSelection = viewer.getStructuredSelection();
226 Object firstElement = structuredSelection.getFirstElement();
227 if(e.widget == btnCollapse){
228 viewer.collapseAll();
229 }
230 else if(e.widget == btnExpand){
231 viewer.expandToLevel(firstElement, AbstractTreeViewer.ALL_LEVELS);
232 }
233 else if(e.widget == btnSelectDirectChildren){
234 Widget item = viewer.testFindItem(firstElement);
235 if(item instanceof TreeItem){
236 viewer.expandToLevel(firstElement, 1);
237 TreeItem treeItem = (TreeItem) item;
238 TreeItem[] childItems = treeItem.getItems();
239 List<TreeItem> childItemList = Arrays.asList(childItems);
240 boolean allChecked = childItemList.stream().allMatch(childItem->childItem.getChecked());
241 childItemList.stream().forEach(childItem->childItem.setChecked(!allChecked));
242 TreeItem parent = getRoot(treeItem);
243 updateItem(parent);
244 }
245 }
246 else if(e.widget == btnSelectAllChildren){
247 Widget item = viewer.testFindItem(firstElement);
248 if(item instanceof TreeItem){
249 viewer.expandToLevel(firstElement, AbstractTreeViewer.ALL_LEVELS);
250 viewer.setSubtreeChecked(firstElement, !((TreeItem) item).getFont().equals(FONT_BOLD));
251 TreeItem parent = getRoot((TreeItem) item);
252 updateItem(parent);
253 ((TreeItem) item).setChecked(false);
254 }
255 }
256 }
257
258 private TreeItem getRoot(TreeItem treeItem) {
259 TreeItem parent = treeItem;
260 while(parent.getParentItem()!=null){
261 parent = parent.getParentItem();
262 }
263 return parent;
264 }
265
266 @Override
267 public void widgetDefaultSelected(SelectionEvent e) {
268 }
269
270 }