cleanup
[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 private boolean allowTopLevelSelection = false;
52
53 public CheckBoxTreeComposite(Composite parent, ITreeContentProvider contentProvider, IBaseLabelProvider labelProvider, int style) {
54 super(parent, style);
55 GridLayout layout = new GridLayout();
56 layout.marginHeight = 0;
57 setLayout(layout);
58
59 Composite toolbar = new Composite(this, SWT.NONE);
60 toolbar.setLayoutData(new GridData(SWT.RIGHT, SWT.CENTER, true, false, 1, 1));
61 GridLayout gl_toolbar = new GridLayout(4, false);
62 gl_toolbar.horizontalSpacing = 4;
63 gl_toolbar.marginHeight = 0;
64 gl_toolbar.verticalSpacing = 0;
65 toolbar.setLayout(gl_toolbar);
66
67 btnCollapse = new Button(toolbar, SWT.NONE);
68 btnCollapse.addSelectionListener(this);
69 btnCollapse.setImage(ImageResources.getImage(ImageResources.COLLAPSE_ALL));
70 btnCollapse.setToolTipText(""); //$NON-NLS-1$
71
72 btnExpand = new Button(toolbar, SWT.NONE);
73 btnExpand.addSelectionListener(this);
74 btnExpand.setImage(ImageResources.getImage(ImageResources.EXPAND));
75 btnExpand.setToolTipText(""); //$NON-NLS-1$
76
77 btnSelectDirectChildren = new Button(toolbar, SWT.NONE);
78 btnSelectDirectChildren.addSelectionListener(this);
79 btnSelectDirectChildren.setImage(ImageResources.getImage(ImageResources.FLAT));
80 btnSelectDirectChildren.setToolTipText(Messages.CheckBoxTreeComposite_SELECT_DIRECT_CHILDREN);
81
82 btnSelectAllChildren = new Button(toolbar, SWT.NONE);
83 btnSelectAllChildren.addSelectionListener(this);
84 btnSelectAllChildren.setImage(ImageResources.getImage(ImageResources.HIERARCHICAL));
85 btnSelectAllChildren.setToolTipText(""); //$NON-NLS-1$
86
87 Tree tree = new Tree(this, SWT.BORDER | SWT.CHECK);
88 tree.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true));
89 tree.addListener(SWT.Selection, event -> {
90 if (event.detail == SWT.CHECK) {
91 TreeItem item = (TreeItem) event.item;
92 if(!allowTopLevelSelection && item.getParentItem()==null){
93 // top level selection not allowed
94 item.setChecked(false);
95 return;
96 }
97 updateItem(item);
98 }
99 });
100
101 viewer = new CheckboxTreeViewer(tree);
102 viewer.setContentProvider(contentProvider);
103 viewer.setLabelProvider(labelProvider);
104 }
105
106
107 private void updateItem(TreeItem treeItem){
108 TreeItem parentItem = treeItem.getParentItem();
109 if(parentItem!=null){
110 updateItem(parentItem);
111 }
112 else{
113 updateChildItems(treeItem);
114 }
115 }
116
117 private void updateChildItems(TreeItem treeItem){
118 treeItem.setFont(FONT_DEFAULT);
119 TreeItem[] children = treeItem.getItems();
120 if(children.length==0){
121 return;
122 }
123 int checkedCount = 0;
124 for (TreeItem child : children) {
125 updateChildItems(child);
126 if(child.getChecked()){
127 if ((child.getFont().equals(FONT_BOLD)) || (child.getItems().length == 0)) {
128 checkedCount++;
129 }
130 //some children are checked
131 treeItem.setFont(FONT_ITALIC);
132 }
133 else if(child.getFont().equals(FONT_ITALIC)
134 || child.getFont().equals(FONT_BOLD)){
135 //some children are checked
136 treeItem.setFont(FONT_ITALIC);
137 }
138 }
139 if(checkedCount==children.length){
140 //all children are checked
141 treeItem.setFont(FONT_BOLD);
142 }
143 else if(!treeItem.getFont().equals(FONT_ITALIC)){
144 if(checkedCount>0){
145 //some children are checked
146 treeItem.setFont(FONT_ITALIC);
147 }
148 else{
149 //no children are checked
150 treeItem.setFont(FONT_DEFAULT);
151 }
152 }
153 }
154
155
156 public CheckboxTreeViewer getViewer() {
157 return viewer;
158 }
159
160 public void setAllowTopLevelSelection(boolean allowTopLevelSelection) {
161 this.allowTopLevelSelection = allowTopLevelSelection;
162 }
163
164 /**
165 * Checks the tree items corresponding to the given elements.<br>
166 * @param elements
167 */
168 public void setCheckedElements(Object[] elements) {
169 viewer.setCheckedElements(elements);
170 for (Object element: elements) {
171 viewer.reveal(element);
172 }
173 TreeItem[] rootItems = viewer.getTree().getItems();
174 for (TreeItem rootItem : rootItems) {
175 updateItem(rootItem);
176 }
177
178 }
179
180 /**
181 * Grays the tree items corresponding to the given elements.<br>
182 * @param elements
183 */
184 public void setGrayedElements(Object[] elements) {
185 viewer.setGrayedElements(elements);
186 for (Object element: elements) {
187 viewer.reveal(element);
188 }
189 TreeItem[] rootItems = viewer.getTree().getItems();
190 for (TreeItem rootItem : rootItems) {
191 updateItem(rootItem);
192 }
193
194 }
195
196 @Override
197 public void widgetSelected(SelectionEvent e) {
198 ITreeSelection structuredSelection = viewer.getStructuredSelection();
199 Object firstElement = structuredSelection.getFirstElement();
200 if(e.widget == btnCollapse){
201 viewer.collapseAll();
202 }
203 else if(e.widget == btnExpand){
204 viewer.expandToLevel(firstElement, AbstractTreeViewer.ALL_LEVELS);
205 }
206 else if(e.widget == btnSelectDirectChildren){
207 Widget item = viewer.testFindItem(firstElement);
208 if(item instanceof TreeItem){
209 viewer.expandToLevel(firstElement, 1);
210 TreeItem treeItem = (TreeItem) item;
211 TreeItem[] childItems = treeItem.getItems();
212 List<TreeItem> childItemList = Arrays.asList(childItems);
213 boolean allChecked = childItemList.stream().allMatch(childItem->childItem.getChecked());
214 childItemList.stream().forEach(childItem->childItem.setChecked(!allChecked));
215 TreeItem parent = getRoot(treeItem);
216 updateItem(parent);
217 }
218 }
219 else if(e.widget == btnSelectAllChildren){
220 Widget item = viewer.testFindItem(firstElement);
221 if(item instanceof TreeItem){
222 viewer.expandToLevel(firstElement, AbstractTreeViewer.ALL_LEVELS);
223 viewer.setSubtreeChecked(firstElement, !((TreeItem) item).getFont().equals(FONT_BOLD));
224 TreeItem parent = getRoot((TreeItem) item);
225 updateItem(parent);
226 ((TreeItem) item).setChecked(false);
227 }
228 }
229 }
230
231 private TreeItem getRoot(TreeItem treeItem) {
232 TreeItem parent = treeItem;
233 while(parent.getParentItem()!=null){
234 parent = parent.getParentItem();
235 }
236 return parent;
237 }
238
239 @Override
240 public void widgetDefaultSelected(SelectionEvent e) {
241 }
242
243 }