Merge branch 'release/5.18.0'
[taxeditor.git] / eu.etaxonomy.taxeditor.editor / src / main / java / eu / etaxonomy / taxeditor / editor / descriptiveDataSet / matrix / CharacterMatrixToolbar.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.editor.descriptiveDataSet.matrix;
10
11 import java.io.IOException;
12 import java.io.StringReader;
13 import java.io.StringWriter;
14 import java.util.Collection;
15 import java.util.Properties;
16 import java.util.function.Consumer;
17
18 import org.apache.commons.lang3.StringUtils;
19 import org.eclipse.jface.viewers.ArrayContentProvider;
20 import org.eclipse.jface.viewers.ComboViewer;
21 import org.eclipse.jface.viewers.LabelProvider;
22 import org.eclipse.nebula.widgets.nattable.NatTable;
23 import org.eclipse.nebula.widgets.nattable.command.VisualRefreshCommand;
24 import org.eclipse.nebula.widgets.nattable.export.command.ExportCommand;
25 import org.eclipse.nebula.widgets.nattable.persistence.PersistenceHelper;
26 import org.eclipse.nebula.widgets.nattable.persistence.command.DisplayPersistenceDialogCommand;
27 import org.eclipse.nebula.widgets.nattable.persistence.command.DisplayPersistenceDialogCommandHandler;
28 import org.eclipse.nebula.widgets.nattable.persistence.command.IStateChangedListener;
29 import org.eclipse.nebula.widgets.nattable.persistence.command.StateChangeEvent;
30 import org.eclipse.nebula.widgets.nattable.persistence.gui.PersistenceDialog;
31 import org.eclipse.nebula.widgets.nattable.tree.command.TreeCollapseAllCommand;
32 import org.eclipse.nebula.widgets.nattable.tree.command.TreeExpandAllCommand;
33 import org.eclipse.nebula.widgets.nattable.viewport.ViewportLayer;
34 import org.eclipse.swt.SWT;
35 import org.eclipse.swt.events.SelectionAdapter;
36 import org.eclipse.swt.events.SelectionEvent;
37 import org.eclipse.swt.graphics.Image;
38 import org.eclipse.swt.layout.GridData;
39 import org.eclipse.swt.layout.GridLayout;
40 import org.eclipse.swt.widgets.Button;
41 import org.eclipse.swt.widgets.Composite;
42 import org.eclipse.swt.widgets.Label;
43
44 import eu.etaxonomy.cdm.api.application.ICdmRepository;
45 import eu.etaxonomy.cdm.api.service.IPreferenceService;
46 import eu.etaxonomy.cdm.model.metadata.CdmPreference;
47 import eu.etaxonomy.cdm.model.metadata.CdmPreference.PrefKey;
48 import eu.etaxonomy.cdm.model.metadata.PreferencePredicate;
49 import eu.etaxonomy.cdm.model.metadata.PreferenceSubject;
50 import eu.etaxonomy.taxeditor.editor.l10n.Messages;
51 import eu.etaxonomy.taxeditor.model.ImageResources;
52 import eu.etaxonomy.taxeditor.model.MessagingUtils;
53 import eu.etaxonomy.taxeditor.preference.CdmPreferenceCache;
54 import eu.etaxonomy.taxeditor.preference.PreferencesUtil;
55 import eu.etaxonomy.taxeditor.store.CdmStore;
56
57 /**
58 * @author pplitzner
59 * @since Jul 9, 2018
60 *
61 */
62 public class CharacterMatrixToolbar extends Composite {
63
64 private CharacterMatrix matrix;
65 private Label wsLabel;
66 private DisplayPersistenceDialogCommandHandler displayPersistenceDialogCommandHandler;
67 private Properties natTableState;
68
69 public CharacterMatrixToolbar(CharacterMatrix matrix, int style) {
70 super(matrix, style);
71 this.matrix = matrix;
72
73 init();
74 }
75
76 private void init() {
77 setLayoutData(new GridData(SWT.FILL, SWT.CENTER, true, false));
78 setLayout(new GridLayout(10, false));
79
80 wsLabel = new Label(this, SWT.NONE);
81
82 Button btnToggleTree = new Button(this, SWT.PUSH);
83 Button btnToggleFlat = new Button(this, SWT.PUSH);
84 Button btnCollapseAll = new Button(this, SWT.PUSH);
85 Button btnExpandAll = new Button(this, SWT.PUSH);
86 Button btnFreezeSuppInfo = new Button(this, SWT.TOGGLE);
87 ComboViewer comboStates = new ComboViewer(this, SWT.DROP_DOWN);
88 Button btnManageState = new Button(this, SWT.PUSH);
89 Button btnExcelExport = new Button(this, SWT.PUSH);
90
91 /**
92 * Toogle tree button
93 */
94 initButton(
95 btnToggleTree,
96 ImageResources.getImage(ImageResources.HIERARCHICAL),
97 Messages.CharacterMatrix_SHOW_HIERARCHY,
98 null,
99 false,
100 true,
101 (e)->matrix.toggleTreeFlat(true, btnToggleFlat, btnToggleTree, btnCollapseAll, btnExpandAll, btnFreezeSuppInfo)
102 );
103
104 /**
105 * Toogle flat button
106 */
107 initButton(
108 btnToggleFlat,
109 ImageResources.getImage(ImageResources.FLAT),
110 Messages.CharacterMatrix_SHOW_FLAT_LIST,
111 null,
112 true,
113 false,
114 (e)->matrix.toggleTreeFlat(false, btnToggleFlat, btnToggleTree, btnCollapseAll, btnExpandAll, btnFreezeSuppInfo)
115 );
116
117 /**
118 *
119 * Collapse button
120 */
121 initButton(
122 btnCollapseAll,
123 ImageResources.getImage(ImageResources.COLLAPSE_ALL),
124 Messages.CharacterMatrix_COLLAPSE,
125 null,
126 true,
127 false,
128 (e)->matrix.getNatTable().doCommand(new TreeCollapseAllCommand())
129 );
130
131 /**
132 * Expand button
133 */
134 initButton(
135 btnExpandAll,
136 ImageResources.getImage(ImageResources.EXPAND_ALL),
137 Messages.CharacterMatrix_EXPAND,
138 null,
139 true,
140 false,
141 (e)->matrix.getNatTable().doCommand(new TreeExpandAllCommand())
142 );
143
144 /**
145 * Freeze supplemental info button
146 */
147 initButton(
148 btnFreezeSuppInfo,
149 ImageResources.getImage(ImageResources.LOCK_ICON),
150 Messages.CharacterMatrix_LOCK_COLUMNS,
151 null,
152 true,
153 true,
154 (e)->{
155 boolean isSelected = btnFreezeSuppInfo.getSelection();
156 matrix.freezeSupplementalColumns(isSelected);
157 btnFreezeSuppInfo.setImage(isSelected?
158 ImageResources.getImage(ImageResources.LOCK_ICON):
159 ImageResources.getImage(ImageResources.LOCK_OPEN_ICON));
160 }
161 );
162
163 /**
164 * Table state persistence
165 */
166 natTableState = new Properties();
167 //load persisted state
168 try {
169 PrefKey key = CdmPreference.NewKey(PreferenceSubject.NewTaxEditorInstance(), PreferencePredicate.CharacterMatrixTableState);
170 CdmPreference preference = CdmPreferenceCache.instance().get(key);
171 if(preference!=null){
172 natTableState.load(new StringReader(preference.getValue()));
173 }
174 } catch (IOException e1) {
175 MessagingUtils.error(getClass(), e1);
176 }
177
178 // create a combobox for showing the available view states
179 Collection<String> availableStates = PersistenceHelper.getAvailableStates(natTableState);
180 if(availableStates.isEmpty()){
181 natTableState.put(StringUtils.EMPTY, StringUtils.EMPTY); // add default config if no states are persisted
182 natTableState.setProperty(PersistenceDialog.ACTIVE_VIEW_CONFIGURATION_KEY, StringUtils.EMPTY);
183 availableStates.add(StringUtils.EMPTY);
184 }
185 comboStates.setLabelProvider(new LabelProvider(){
186 @Override
187 public String getText(Object element) {
188 if(element instanceof String && ((String) element).isEmpty()){
189 return Messages.CharacterMatrix_DEFAULT;
190 }
191 return super.getText(element);
192 }
193 });
194 comboStates.setContentProvider(new ArrayContentProvider());
195 comboStates.addSelectionChangedListener(e->
196 {
197 int index = comboStates.getCombo().getSelectionIndex();
198 if (index >= 0) {
199 String selected = comboStates.getCombo().getItem(index);
200 // load the state
201 matrix.getNatTable().loadState(selected, natTableState);
202 natTableState.setProperty(PersistenceDialog.ACTIVE_VIEW_CONFIGURATION_KEY, selected);
203 }
204 });
205 comboStates.setInput(availableStates);
206 if(comboStates.getCombo().getItemCount()>0){
207 selectStateItem(comboStates, Messages.CharacterMatrix_DEFAULT);
208 }
209
210 displayPersistenceDialogCommandHandler = new DisplayPersistenceDialogCommandHandler(natTableState, matrix.getNatTable());
211 // add listener to update the combo on view state management changes
212 displayPersistenceDialogCommandHandler.addStateChangeListener(new IStateChangedListener() {
213 @Override
214 public void handleStateChange(StateChangeEvent event) {
215 comboStates.setInput(PersistenceHelper.getAvailableStates(natTableState));
216 selectStateItem(comboStates, event.getViewConfigName());
217 }
218 });
219
220 // add button to show dialog
221 btnManageState.setImage(ImageResources.getImage(ImageResources.SETTINGS));
222 btnManageState.setToolTipText(Messages.CharacterMatrix_VIEW_CONFIG);
223 btnManageState.addSelectionListener(new SelectionAdapter() {
224 @Override
225 public void widgetSelected(SelectionEvent e) {
226 getNatTableState().remove(NatTable.INITIAL_PAINT_COMPLETE_FLAG);
227 matrix.getNatTable().doCommand(new DisplayPersistenceDialogCommand(matrix.getNatTable()));
228 Object activeConfig = natTableState.get(PersistenceDialog.ACTIVE_VIEW_CONFIGURATION_KEY);
229 if(activeConfig!=null){
230 selectStateItem(comboStates, activeConfig.toString());
231 }
232 persistTableState();
233 }
234 });
235
236 /**
237 * excel export
238 */
239 btnExcelExport.setToolTipText(Messages.CharacterMatrix_EXPORT);
240 btnExcelExport.setImage(ImageResources.getImage(ImageResources.EXPORT));
241 btnExcelExport.addSelectionListener(new SelectionAdapter() {
242 @Override
243 public void widgetSelected(SelectionEvent e) {
244 // hack for fixing #8332
245 // By scrolling for only 1 pixel the export then exports all rows
246 ViewportLayer viewportLayer = matrix.getBodyLayer().getViewportLayer();
247 if(viewportLayer.getOrigin().getY()==0){
248 viewportLayer.setOriginY(1);
249 }
250 matrix.getNatTable().doCommand(
251 new ExportCommand(
252 matrix.getNatTable().getConfigRegistry(),
253 matrix.getNatTable().getShell()));
254 matrix.getNatTable().doCommand(new VisualRefreshCommand());
255 }
256 });
257
258 }
259
260 private void persistTableState() {
261 if(matrix.getNatTableState()!=null){
262 StringWriter writer = new StringWriter();
263 try {
264 matrix.getNatTableState().store(writer, null);
265 ICdmRepository controller = CdmStore.getCurrentApplicationConfiguration();
266 if (controller != null){
267 IPreferenceService service = controller.getPreferenceService();
268 CdmPreference pref = CdmPreference.NewTaxEditorInstance(PreferencePredicate.CharacterMatrixTableState, writer.toString());
269 service.set(pref);
270 PreferencesUtil.updateDBPreferences();
271 }
272 } catch (IOException e) {
273 MessagingUtils.error(getClass(), e);
274 }
275 }
276 }
277
278 private void selectStateItem(ComboViewer comboStates, String stateName){
279 if(stateName.equals(StringUtils.EMPTY)){
280 stateName = Messages.CharacterMatrix_DEFAULT;
281 }
282 String[] items = comboStates.getCombo().getItems();
283 for(int i=0;i<items.length;i++){
284 if(items[i].equals(stateName)){
285 comboStates.getCombo().select(i);
286 break;
287 }
288 }
289 }
290
291 private void initButton(Button button, Image image, String tooltipText,
292 String label, boolean enabled, boolean selected, Consumer<SelectionEvent> widgetSelected){
293 if(image!=null){
294 button.setImage(image);
295 }
296 if(label!=null){
297 button.setText(label);
298 }
299 if(tooltipText!=null){
300 button.setToolTipText(tooltipText);
301 }
302 button.setSelection(selected);
303 button.setEnabled(enabled);
304 button.addSelectionListener(new SelectionAdapter() {
305 @Override
306 public void widgetSelected(SelectionEvent e) {
307 widgetSelected.accept(e);
308 }
309 });
310 }
311
312 public Label getWsLabel() {
313 return wsLabel;
314 }
315
316 public Properties getNatTableState() {
317 return natTableState;
318 }
319
320 public DisplayPersistenceDialogCommandHandler getDisplayPersistenceDialogCommandHandler() {
321 return displayPersistenceDialogCommandHandler;
322 }
323 }