com.bdaum.zoom.ui.internal.preferences.MetadataPreferencePage.java Source code

Java tutorial

Introduction

Here is the source code for com.bdaum.zoom.ui.internal.preferences.MetadataPreferencePage.java

Source

/*
 * This file is part of the ZoRa project: http://www.photozora.org.
 *
 * ZoRa is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 2 of the License, or
 * (at your option) any later version.
 *
 * ZoRa is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with ZoRa; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 *
 * (c) 2009-2018 Berthold Daum  
 */

package com.bdaum.zoom.ui.internal.preferences;

import java.text.NumberFormat;
import java.text.ParseException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.StringTokenizer;

import org.eclipse.jface.preference.IPreferenceStore;
import org.eclipse.jface.viewers.CellEditor;
import org.eclipse.jface.viewers.CheckStateChangedEvent;
import org.eclipse.jface.viewers.CheckboxTreeViewer;
import org.eclipse.jface.viewers.EditingSupport;
import org.eclipse.jface.viewers.ICellEditorValidator;
import org.eclipse.jface.viewers.ICheckStateListener;
import org.eclipse.jface.viewers.TextCellEditor;
import org.eclipse.jface.viewers.TreeViewer;
import org.eclipse.jface.viewers.TreeViewerColumn;
import org.eclipse.jface.viewers.Viewer;
import org.eclipse.jface.viewers.ViewerFilter;
import org.eclipse.swt.SWT;
import org.eclipse.swt.custom.BusyIndicator;
import org.eclipse.swt.events.SelectionAdapter;
import org.eclipse.swt.events.SelectionEvent;
import org.eclipse.swt.graphics.Color;
import org.eclipse.swt.layout.GridData;
import org.eclipse.swt.layout.GridLayout;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Label;
import org.eclipse.ui.IWorkbench;
import org.eclipse.ui.dialogs.ContainerCheckedTreeViewer;

import com.bdaum.zoom.core.Core;
import com.bdaum.zoom.core.QueryField;
import com.bdaum.zoom.css.ZColumnLabelProvider;
import com.bdaum.zoom.ui.internal.HelpContextIds;
import com.bdaum.zoom.ui.internal.UiActivator;
import com.bdaum.zoom.ui.internal.UiUtilities;
import com.bdaum.zoom.ui.internal.ZViewerComparator;
import com.bdaum.zoom.ui.internal.dialogs.AllNoneGroup;
import com.bdaum.zoom.ui.internal.dialogs.MetadataContentProvider;
import com.bdaum.zoom.ui.internal.dialogs.MetadataLabelProvider;
import com.bdaum.zoom.ui.internal.widgets.ExpandCollapseGroup;
import com.bdaum.zoom.ui.internal.widgets.JpegMetaGroup;
import com.bdaum.zoom.ui.preferences.AbstractPreferencePage;
import com.bdaum.zoom.ui.preferences.PreferenceConstants;

public class MetadataPreferencePage extends AbstractPreferencePage {

    private static final Object[] EMPTY = new Object[0];
    private final static NumberFormat af = (NumberFormat.getNumberInstance());
    private static final String SEC = Messages.getString("MetadataPreferencePage.sec"); //$NON-NLS-1$

    public class ToleranceLabelProvider extends ZColumnLabelProvider {

        @Override
        public String getText(Object element) {
            if (element instanceof QueryField) {
                QueryField qfield = (QueryField) element;
                Float tolerance = toleranceMap.get(qfield.getKey());
                if (tolerance != null) {
                    if (tolerance > 0)
                        return (int) tolerance.floatValue() + " %"; //$NON-NLS-1$
                    if (tolerance < 0) {
                        tolerance = -tolerance;
                        switch (qfield.getType()) {
                        case QueryField.T_INTEGER:
                        case QueryField.T_POSITIVEINTEGER:
                        case QueryField.T_POSITIVELONG:
                        case QueryField.T_LONG:
                            return String.valueOf((int) tolerance.floatValue());
                        case QueryField.T_FLOAT:
                        case QueryField.T_FLOATB:
                        case QueryField.T_CURRENCY:
                        case QueryField.T_POSITIVEFLOAT:
                            af.setMaximumFractionDigits(qfield.getMaxlength());
                            return af.format(tolerance);
                        case QueryField.T_DATE:
                            return String.valueOf((int) tolerance.floatValue() / 1000) + SEC;
                        }
                    }
                }
            }
            return null;
        }
    }

    private static final Object[] EMPTYOBJECTS = new Object[0];
    public static final String ID = "com.bdaum.zoom.ui.MetadataPreferencePage"; //$NON-NLS-1$
    private static final Object ESSENTIAL = "essential"; //$NON-NLS-1$

    private CheckboxTreeViewer essentialsViewer;
    private CheckboxTreeViewer hoverViewer;
    private TreeViewer tolerancesViewer;
    private Map<String, Float> toleranceMap = new HashMap<String, Float>(50);
    private TreeViewer exportViewer;
    private JpegMetaGroup jpegGroup;
    private ContainerCheckedTreeViewer tuningViewer;
    private Set<String> alwaysIndexed = new HashSet<>();

    public MetadataPreferencePage() {
        setDescription(Messages.getString("MetadataPreferencePage.what_to_do")); //$NON-NLS-1$
        alwaysIndexed = new HashSet<>(Core
                .fromStringList(getPreferenceStore().getDefaultString(PreferenceConstants.METADATATUNING), "\n")); //$NON-NLS-1$
    }

    @Override
    public void applyData(Object data) {
        if (ESSENTIAL.equals(data)) {
            tabFolder.setSelection(0);
            fillValues();
        }
    }

    @Override
    protected void createPageContents(Composite comp) {
        setHelp(HelpContextIds.METADATA_PREFERENCE_PAGE);
        createTabFolder(comp, "Meta"); //$NON-NLS-1$
        final Composite essentialsGroup = UiUtilities.createTabPage(tabFolder,
                Messages.getString("MetadataPreferencePage.essential_metadata"), //$NON-NLS-1$
                Messages.getString("MetadataPreferencePage.essential_tooltip")); //$NON-NLS-1$
        essentialsGroup.setLayout(new GridLayout(2, false));
        essentialsViewer = createViewerGroup(essentialsGroup, null, new MetadataLabelProvider());
        final Composite hoverGroup = UiUtilities.createTabPage(tabFolder,
                Messages.getString("MetadataPreferencePage.hover_metadata"), //$NON-NLS-1$
                Messages.getString("MetadataPreferencePage.hover_tooltip")); //$NON-NLS-1$
        hoverGroup.setLayout(new GridLayout(2, false));
        hoverViewer = createViewerGroup(hoverGroup, null, new MetadataLabelProvider());
        final Composite tolerancesGroup = UiUtilities.createTabPage(tabFolder,
                Messages.getString("MetadataPreferencePage.tolerances"), //$NON-NLS-1$
                Messages.getString("MetadataPreferencePage.tolerance_tooltip")); //$NON-NLS-1$
        tolerancesGroup.setLayout(new GridLayout());
        tolerancesViewer = createTolerancesViewer(tolerancesGroup);
        final Composite exportGroup = UiUtilities.createTabPage(tabFolder,
                Messages.getString("MetadataPreferencePage.export"), //$NON-NLS-1$
                Messages.getString("MetadataPreferencePage.export_tooltip")); //$NON-NLS-1$
        exportGroup.setLayout(new GridLayout());
        Composite viewerGroup = new Composite(exportGroup, SWT.NONE);
        viewerGroup.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true));
        viewerGroup.setLayout(new GridLayout(2, false));
        exportViewer = createViewerGroup(viewerGroup, null, new MetadataLabelProvider());
        jpegGroup = new JpegMetaGroup(exportGroup, SWT.NONE);
        final Composite tuningGroup = UiUtilities.createTabPage(tabFolder,
                Messages.getString("MetadataPreferencePage.tuning"), //$NON-NLS-1$
                Messages.getString("MetadataPreferencePage.tuning_tooltip")); //$NON-NLS-1$
        tuningGroup.setLayout(new GridLayout(2, false));
        Label label = new Label(tuningGroup, SWT.NONE);
        label.setLayoutData(new GridData(SWT.FILL, SWT.BEGINNING, true, false, 2, 1));
        label.setText(Messages.getString("MetadataPreferencePage.tuning_msg")); //$NON-NLS-1$
        tuningViewer = createViewerGroup(tuningGroup, new ViewerFilter() {
            @Override
            public boolean select(Viewer aViewer, Object parentElement, Object element) {
                if (element instanceof QueryField) {
                    QueryField qfield = (QueryField) element;
                    return qfield.hasChildren() || qfield.isUiField() && !qfield.isStruct() && qfield.isQuery();
                }
                return false;
            }
        }, new MetadataLabelProvider() {
            @Override
            protected Color getForeground(Object element) {
                if (element instanceof QueryField && alwaysIndexed.contains(((QueryField) element).getKey()))
                    return super.getDisabledForeground(element);
                return super.getForeground(element);
            }
        });
        tuningViewer.addCheckStateListener(new ICheckStateListener() {
            @Override
            public void checkStateChanged(CheckStateChangedEvent event) {
                if (!event.getChecked()) {
                    Object element = event.getElement();
                    if (element instanceof QueryField && alwaysIndexed.contains(((QueryField) element).getKey()))
                        tuningViewer.setChecked(element, true);
                }
            }
        });
        jpegGroup.setSelection(getPreferenceStore().getBoolean(PreferenceConstants.JPEGMETADATA));
        initTabFolder(0);
        fillValues();
        tabFolder.addSelectionListener(new SelectionAdapter() {
            @Override
            public void widgetSelected(SelectionEvent e) {
                fillValues();
            }
        });
    }

    protected void fillValues() {
        switch (tabFolder.getSelectionIndex()) {
        case 0:
            fillViewer(essentialsViewer, getPreferenceStore().getString(PreferenceConstants.ESSENTIALMETADATA), 2,
                    false);
            break;
        case 1:
            fillViewer(hoverViewer, getPreferenceStore().getString(PreferenceConstants.HOVERMETADATA), 2, false);
            break;
        case 2:
            fillViewer(tolerancesViewer, getPreferenceStore().getString(PreferenceConstants.METADATATOLERANCES), 2,
                    false);
            break;
        case 3:
            fillViewer(exportViewer, getPreferenceStore().getString(PreferenceConstants.EXPORTMETADATA), 2, false);
            break;
        case 4:
            fillViewer(tuningViewer, getPreferenceStore().getString(PreferenceConstants.METADATATUNING), 2, false);
            break;
        }
    }

    private TreeViewer createTolerancesViewer(Composite comp) {
        ExpandCollapseGroup toleranceExpandCollapseGroup = new ExpandCollapseGroup(comp, SWT.NONE);
        final TreeViewer viewer = new TreeViewer(comp,
                SWT.SINGLE | SWT.H_SCROLL | SWT.V_SCROLL | SWT.BORDER | SWT.FULL_SELECTION);
        viewer.getControl().setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true));
        toleranceExpandCollapseGroup.setViewer(viewer);
        viewer.getTree().setLinesVisible(true);
        TreeViewerColumn col1 = new TreeViewerColumn(viewer, SWT.NONE);
        col1.getColumn().setWidth(250);
        col1.setLabelProvider(new MetadataLabelProvider());
        TreeViewerColumn col2 = new TreeViewerColumn(viewer, SWT.NONE);
        col2.getColumn().setWidth(80);
        final ToleranceLabelProvider labelProvider = new ToleranceLabelProvider();
        col2.setLabelProvider(labelProvider);
        col2.setEditingSupport(new EditingSupport(viewer) {
            @Override
            protected void setValue(Object element, Object value) {
                if (element instanceof QueryField) {
                    QueryField qfield = (QueryField) element;
                    String key = qfield.getKey();
                    String s = String.valueOf(value);
                    float v;
                    if (s.endsWith("%")) //$NON-NLS-1$
                        v = Integer.parseInt(s.substring(0, s.length() - 1).trim());
                    else
                        try {
                            af.setMaximumFractionDigits(8);
                            v = -af.parse(s.trim()).floatValue();
                            if (qfield.getType() == QueryField.T_DATE)
                                v = 1000 * v;
                        } catch (ParseException e) {
                            v = 0f;
                        }
                    toleranceMap.put(key, v);
                    viewer.update(element, null);
                }
            }

            @Override
            protected Object getValue(Object element) {
                String text = labelProvider.getText(element);
                if (text.endsWith(SEC))
                    return text.substring(0, text.length() - SEC.length());
                return text;
            }

            @Override
            protected CellEditor getCellEditor(Object element) {
                if (element instanceof QueryField) {
                    final int type = ((QueryField) element).getType();
                    TextCellEditor editor = new TextCellEditor(viewer.getTree());
                    editor.setValidator(new ICellEditorValidator() {
                        public String isValid(Object value) {
                            String s = String.valueOf(value);
                            if (s.endsWith("%")) { //$NON-NLS-1$
                                try {
                                    if (Integer.parseInt(s.substring(0, s.length() - 1).trim()) < 0)
                                        return Messages.getString("MetadataPreferencePage.must_not_be_negative"); //$NON-NLS-1$
                                    if (type == QueryField.T_DATE)
                                        return Messages
                                                .getString("MetadataPreferencePage.percent_not_allowed_for_date"); //$NON-NLS-1$
                                    return null;
                                } catch (NumberFormatException e) {
                                    return Messages.getString("MetadataPreferencePage.bad_integer"); //$NON-NLS-1$
                                }
                            }
                            if (type == QueryField.T_POSITIVEINTEGER || type == QueryField.T_INTEGER) {
                                try {
                                    if (Integer.parseInt(s.substring(0, s.length() - 1).trim()) < 0)
                                        return Messages.getString("MetadataPreferencePage.must_not_be_negative"); //$NON-NLS-1$
                                    return null;
                                } catch (NumberFormatException e) {
                                    return Messages.getString("MetadataPreferencePage.bad_integer"); //$NON-NLS-1$
                                }
                            } else if (type == QueryField.T_POSITIVELONG || type == QueryField.T_LONG) {
                                try {
                                    if (Long.parseLong(s.substring(0, s.length() - 1).trim()) < 0)
                                        return Messages.getString("MetadataPreferencePage.must_not_be_negative"); //$NON-NLS-1$
                                    return null;
                                } catch (NumberFormatException e) {
                                    return Messages.getString("MetadataPreferencePage.bad_integer"); //$NON-NLS-1$
                                }
                            }
                            try {
                                af.setMaximumFractionDigits(8);
                                if (af.parse(s.trim()).floatValue() < 0)
                                    return Messages.getString("MetadataPreferencePage.must_not_be_negative"); //$NON-NLS-1$
                                return null;
                            } catch (ParseException e) {
                                return Messages.getString("MetadataPreferencePage.bad_floating_point"); //$NON-NLS-1$
                            }
                        }
                    });
                    return editor;
                }
                return null;
            }

            @Override
            protected boolean canEdit(Object element) {
                if (element instanceof QueryField)
                    return ((QueryField) element).getTolerance() != 0f;
                return false;
            }
        });
        viewer.setContentProvider(new MetadataContentProvider());
        viewer.setComparator(ZViewerComparator.INSTANCE);
        UiUtilities.installDoubleClickExpansion(viewer);
        viewer.setFilters(new ViewerFilter[] { new ViewerFilter() {
            @Override
            public boolean select(Viewer aViewer, Object parentElement, Object element) {
                if (element instanceof QueryField) {
                    QueryField qfield = (QueryField) element;
                    return (qfield.hasChildren() || qfield.isUiField())
                            && hostsToleranceValue((QueryField) element);
                }
                return false;
            }

            private boolean hostsToleranceValue(QueryField qfield) {
                if (qfield.getTolerance() != 0f)
                    return true;
                for (QueryField child : qfield.getChildren())
                    if (hostsToleranceValue(child))
                        return true;
                return false;
            }
        } });
        return viewer;
    }

    @SuppressWarnings("unused")
    private static ContainerCheckedTreeViewer createViewerGroup(Composite comp, ViewerFilter filter,
            MetadataLabelProvider labelProvider) {
        ExpandCollapseGroup expandCollapseGroup = new ExpandCollapseGroup(comp, SWT.NONE);
        new Label(comp, SWT.NONE);
        final ContainerCheckedTreeViewer viewer = new ContainerCheckedTreeViewer(comp,
                SWT.SINGLE | SWT.H_SCROLL | SWT.V_SCROLL | SWT.BORDER);
        viewer.getControl().setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true));
        expandCollapseGroup.setViewer(viewer);
        viewer.setLabelProvider(labelProvider);
        viewer.setContentProvider(new MetadataContentProvider());
        viewer.setFilters(new ViewerFilter[] { filter != null ? filter : new ViewerFilter() {
            @Override
            public boolean select(Viewer aViewer, Object parentElement, Object element) {
                if (element instanceof QueryField) {
                    QueryField qfield = (QueryField) element;
                    return qfield.hasChildren() || qfield.isUiField();
                }
                return false;
            }
        } });
        viewer.setComparator(ZViewerComparator.INSTANCE);
        UiUtilities.installDoubleClickExpansion(viewer);
        new AllNoneGroup(comp, new SelectionAdapter() {
            @Override
            public void widgetSelected(SelectionEvent e) {
                if (e.widget.getData() == AllNoneGroup.ALL) {
                    viewer.setGrayedElements(EMPTY);
                    viewer.setCheckedElements(QueryField.getQueryFields().toArray());
                } else
                    viewer.setCheckedElements(EMPTY);
            }
        });
        return viewer;
    }

    private void fillViewer(final TreeViewer viewer, final String ess, final int level, boolean force) {
        if (viewer.getInput() == null || force)
            BusyIndicator.showWhile(viewer.getControl().getDisplay(), () -> {
                if (viewer.getInput() == null) {
                    viewer.setInput(QueryField.ALL);
                    if (level >= 0)
                        viewer.expandToLevel(level);
                }
                StringTokenizer st = new StringTokenizer(ess, "\n"); //$NON-NLS-1$
                if (viewer instanceof CheckboxTreeViewer) {
                    List<QueryField> fields = new ArrayList<QueryField>();
                    while (st.hasMoreTokens()) {
                        QueryField qfield = QueryField.findQueryField(st.nextToken());
                        if (qfield != null)
                            fields.add(qfield);
                    }
                    ((CheckboxTreeViewer) viewer).setCheckedElements(fields.toArray());
                } else
                    while (st.hasMoreTokens()) {
                        String id = st.nextToken();
                        int p = id.lastIndexOf("="); //$NON-NLS-1$
                        if (p > 0) {
                            try {
                                toleranceMap.put(id.substring(0, p), Float.parseFloat(id.substring(p + 1)));
                            } catch (NumberFormatException e) {
                                // ignore
                            }
                        }
                    }
            });
    }

    @Override
    public void init(IWorkbench wb) {
        super.init(wb);
        setTitle(Messages.getString("MetadataPreferencePage.metadata_configuration")); //$NON-NLS-1$
        setMessage(Messages.getString("MetadataPreferencePage.select_essential_and_hover")); //$NON-NLS-1$
    }

    @Override
    protected IPreferenceStore doGetPreferenceStore() {
        return UiActivator.getDefault().getPreferenceStore();
    }

    @Override
    protected void doPerformDefaults() {
        setDefaults(essentialsViewer, PreferenceConstants.ESSENTIALMETADATA);
        setDefaults(hoverViewer, PreferenceConstants.HOVERMETADATA);
        setDefaults(tolerancesViewer, PreferenceConstants.METADATATOLERANCES);
        setDefaults(exportViewer, PreferenceConstants.EXPORTMETADATA);
        setDefaults(tuningViewer, PreferenceConstants.METADATATUNING);
        tolerancesViewer.setInput(QueryField.ALL);
        IPreferenceStore preferenceStore = getPreferenceStore();
        preferenceStore.setValue(PreferenceConstants.JPEGMETADATA,
                preferenceStore.getDefaultBoolean(PreferenceConstants.JPEGMETADATA));
        jpegGroup.setSelection(getPreferenceStore().getBoolean(PreferenceConstants.JPEGMETADATA));
    }

    private void setDefaults(TreeViewer viewer, String key) {
        if (viewer instanceof CheckboxTreeViewer)
            ((CheckboxTreeViewer) viewer).setCheckedElements(EMPTYOBJECTS);
        IPreferenceStore preferenceStore = getPreferenceStore();
        String ess = preferenceStore.getDefaultString(key);
        preferenceStore.setValue(key, ess);
        fillViewer(viewer, ess, -1, true);
    }

    @Override
    protected void doPerformOk() {
        saveValues(essentialsViewer, PreferenceConstants.ESSENTIALMETADATA);
        saveValues(hoverViewer, PreferenceConstants.HOVERMETADATA);
        saveValues(exportViewer, PreferenceConstants.EXPORTMETADATA);
        saveValues(tolerancesViewer, PreferenceConstants.METADATATOLERANCES);
        saveValues(tuningViewer, PreferenceConstants.METADATATUNING);
        getPreferenceStore().setValue(PreferenceConstants.JPEGMETADATA, jpegGroup.getSelection());
    }

    private void saveValues(TreeViewer viewer, String pkey) {
        if (viewer.getInput() != null) {
            StringBuilder sb = new StringBuilder();
            if (viewer instanceof CheckboxTreeViewer) {
                for (Object object : ((CheckboxTreeViewer) viewer).getCheckedElements())
                    if (object instanceof QueryField) {
                        QueryField queryField = (QueryField) object;
                        String id = queryField.getId();
                        if (id != null && queryField.getChildren().length == 0) {
                            if (sb.length() > 0)
                                sb.append('\n');
                            sb.append(id);
                        }
                    }
            } else
                for (String key : toleranceMap.keySet()) {
                    if (sb.length() > 0)
                        sb.append('\n');
                    sb.append(key).append("=").append(toleranceMap.get(key)); //$NON-NLS-1$
                }
            getPreferenceStore().setValue(pkey, sb.toString());
        }
    }

}