Package org.cishell.reference.gui.persistence.save

Source Code of org.cishell.reference.gui.persistence.save.SaveDataChooser$CompareAlphabetically

/*
* InfoVis CyberInfrastructure: A Data-Code-Compute Resource for Research
* and Education in Information Visualization (http://iv.slis.indiana.edu/).
*
* Created on Jan 28, 2005 at Indiana University.
*/
package org.cishell.reference.gui.persistence.save;

import java.util.Arrays;
import java.util.Comparator;
import java.util.Dictionary;
import java.util.Enumeration;
import java.util.HashMap;
import java.util.Map;

import org.cishell.framework.CIShellContext;
import org.cishell.framework.algorithm.AlgorithmProperty;
import org.cishell.framework.data.Data;
import org.cishell.reference.gui.guibuilder.swt.builder.AbstractDialog;
import org.cishell.service.conversion.Converter;
import org.eclipse.swt.SWT;
import org.eclipse.swt.custom.StyleRange;
import org.eclipse.swt.custom.StyledText;
import org.eclipse.swt.events.MouseAdapter;
import org.eclipse.swt.events.MouseEvent;
import org.eclipse.swt.events.SelectionAdapter;
import org.eclipse.swt.events.SelectionEvent;
import org.eclipse.swt.graphics.Image;
import org.eclipse.swt.layout.FillLayout;
import org.eclipse.swt.layout.GridData;
import org.eclipse.swt.layout.GridLayout;
import org.eclipse.swt.widgets.Button;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Display;
import org.eclipse.swt.widgets.Group;
import org.eclipse.swt.widgets.List;
import org.eclipse.swt.widgets.Shell;
import org.osgi.framework.ServiceReference;

/**
* SaveDataChooser is a simple user interface to allow for selection
* among several persisters that support the selected model, in the event
* that more than one is found.
*/
/* TODO
* If we make a file viewer service, remove this
* Otherwise move to File View algorithm
*/
public class SaveDataChooser extends AbstractDialog implements AlgorithmProperty {
  public static final Image QUESTION_ICON =
      Display.getCurrent().getSystemImage(SWT.ICON_QUESTION);

    protected Data data;
    protected Converter[] converters;
    private List converterListComponent;
    private StyledText detailPane;
    CIShellContext ciShellContext;

    /**
     * Creates a new SaveChooser object.
     *
     * @param data The data object to save
     * @param parent The parent shell
     * @param converters The array of converters to persist the data
     * @param title Title of the Window
     * @param brandPluginID The plugin that supplies the branding
     * @param ciShellContext The CIShellContext to retrieve available services
     */
    public SaveDataChooser(
        Data data,
        Shell parent,
        Converter[] converters,
        String title,
        CIShellContext ciShellContext) {
      super(parent, title, QUESTION_ICON);
        this.data = data;       
        this.converters = alphabetizeConverters(filterConverters(converters));
        this.ciShellContext = ciShellContext;
    }  

    /**
     * Initialize the GUI for the chooser
     * @param parent The parent window
     * @return The new window containing the chooser
     */
    private Composite initializeGUI(Composite parent) {
        Composite content = new Composite(parent, SWT.NONE);
        GridLayout layout = new GridLayout();
        layout.numColumns = 2;
        content.setLayout(layout);

        Group converterGroup = new Group(content, SWT.NONE);
        converterGroup.setText("Pick the Output Data Type");
        converterGroup.setLayout(new FillLayout());
        GridData persisterData = new GridData(GridData.FILL_BOTH);
        persisterData.widthHint = 200;
        converterGroup.setLayoutData(persisterData);

        converterListComponent =
          new List(converterGroup, SWT.H_SCROLL | SWT.V_SCROLL | SWT.SINGLE);
        initializeConverterListComponent();
        converterListComponent.addMouseListener(new MouseAdapter() {
          public void mouseDoubleClick(MouseEvent mouseEvent) {
            List list = (List)mouseEvent.getSource();
            int selection = list.getSelectionIndex();
           
            if (selection != -1) {
              selectionMade(selection);
            }
          }
        });
        converterListComponent.addSelectionListener(new SelectionAdapter() {
          public void widgetSelected(SelectionEvent selectionEvent) {
            List list = (List)selectionEvent.getSource();
            int selection = list.getSelectionIndex();

            if (selection != -1) {
              updateDetailPane(converters[selection]);
            }
          }
        });

        Group detailsGroup = new Group(content, SWT.NONE);
        detailsGroup.setText("Details");
        detailsGroup.setLayout(new FillLayout());       
        GridData detailsData = new GridData(GridData.FILL_BOTH);
        detailsData.widthHint = 200;
        detailsGroup.setLayoutData(detailsData);

        detailPane = initializeDetailPane(detailsGroup);

        // Select the first item by default.
        converterListComponent.setSelection(0);
        updateDetailPane(converters[0]);

        return content;
    }

    /**
     * Initialize the Listbox of Persisters using the stored Persister array
     */
    private void initializeConverterListComponent() {
        for (int ii = 0; ii < converters.length; ii++) {
      if (converters[ii] != null) {
        Dictionary converterProperties = converters[ii].getProperties();

        // Get the name of the persister from the property map.
        String outData = null;
               
                ServiceReference[] serviceReferences = converters[ii].getConverterChain();

                if ((serviceReferences != null) && (serviceReferences.length > 0)) {
                    outData = (String)serviceReferences[serviceReferences.length - 1].getProperty(
                      AlgorithmProperty.LABEL);
                }

                if (outData == null) {
                    outData = (String)converterProperties.get(AlgorithmProperty.LABEL);
                }

        /*
         * If someone was sloppy enough to not provide a name, then use the name of the
         *  class instead.
         */
        if ((outData == null) || (outData.length() == 0)) {
          outData = converters[ii].getClass().getName();
        }

        converterListComponent.add(outData);
      }
    }
    }

    /**
   * Sets up the DetailPane where the details from the Persister PropertyMaps
   * are displayed.
   *
   * @param detailsGroup
   *            The detail pane to init
   * @return A style of the text
   */
    private StyledText initializeDetailPane(Group detailsGroup) {
        StyledText detailPane = new StyledText(detailsGroup, SWT.H_SCROLL | SWT.V_SCROLL);
        detailPane.setEditable(false);
        detailPane.getCaret().setVisible(false);

        return detailPane;
    }

    /**
     * Changes the information displayed in the DetailsPane whenever a new Persister
     * is selected.
     * @param converter A converter that contains the properties for the detail pane
     */
    private void updateDetailPane(Converter converter) {
        Dictionary converterProperties = converter.getProperties();
        Enumeration converterPropertiesKeys = converterProperties.keys();

        detailPane.setText("");

        while (converterPropertiesKeys.hasMoreElements()) {
            Object key = converterPropertiesKeys.nextElement();
            Object value = converterProperties.get(key);
 
            StyleRange styleRange = new StyleRange();
            styleRange.start = detailPane.getText().length();
            detailPane.append(key + ":\n");
            styleRange.length = key.toString().length() + 1;
            styleRange.fontStyle = SWT.BOLD;
            detailPane.setStyleRange(styleRange);
 
            detailPane.append(value + "\n");
        }
    }
   
    /**
     * In allConverters, there are sometimes more than one
     * that converts to a single data type. When the
     * chooser pops up, this is confusing to the user, since it
     * will, for instance, display two 'Pajek.net' choices.
     *
     * This method attempts to choose the best converter for each
     * out_data format, choosing based on lossiness primarily, and
     * length of converter chain secondarily.
     * @param allConverters All the converters starting with
     * the original file's data type (that is, any type in its class heirarchy)
     * and ending in a file format.
     * @return allConverters, with redudant out file formats removed.
     */
    private Converter[] filterConverters(Converter[] allConverters) {
      Map lastInDataToConverter = new HashMap();
     
      for (int ii = 0; ii < allConverters.length; ii++) {
        Converter converter = allConverters[ii];

        /*
         * To uniquely identify an XML file, we need to know what kind of XML it was so we look
         *  at the input data type of the last converter.
         */
        String lastInputData = getLastConverterInData(converter);

        if (lastInDataToConverter.containsKey(lastInputData)) {
          Converter alreadyStoredConverter =
            (Converter)lastInDataToConverter.get(lastInputData);
          Converter chosenConverter =
            returnPreferredConverter(converter, alreadyStoredConverter);
          lastInDataToConverter.put(lastInputData, chosenConverter);
        } else {
          lastInDataToConverter.put(lastInputData, converter);
        }
      }
     
      return (Converter[]) lastInDataToConverter.values().toArray(new Converter[0]);
    }
   
    private String getLastConverterInData(Converter converter) {
      ServiceReference[] convChain = converter.getConverterChain();

      if (convChain.length >= 1) {
        ServiceReference lastConverter = convChain[convChain.length - 1];
        String lastInData = (String) lastConverter.getProperty("in_data");

        return lastInData;
      } else {
        return "";
      }
    }
   
    /**
     * Returns whichever converter is better to show to the user in the chooser,
     * based on lossiness, and length of converter chain
     * @param converter1 A converter with the same out_data type as the other
     * @param converter2 A converter with the same out_data type as the other
     * @return The preferred converter of the two
     */
    private Converter returnPreferredConverter(Converter converter1, Converter converter2) {
      Dictionary converter1Properties = converter1.getProperties();
      String converter1Lossiness = (String)converter1Properties.get(CONVERSION);
      int converter1Quality = determineQuality(converter1Lossiness);

      Dictionary converter2Properties = converter2.getProperties();
      String converter2Lossiness = (String)converter2Properties.get(CONVERSION);
      int converter2Quality = determineQuality(converter2Lossiness);
     
      if (converter1Quality > converter2Quality) {
        return converter1;
      } else if (converter2Quality > converter1Quality) {
        return converter2;
      } else {
        // They are tied. Look at converter chain length.
       
        int converter1Length = converter1.getConverterChain().length;
        int converter2Length = converter2.getConverterChain().length;

        if (converter1Length > converter2Length) {
          return converter2;
        } else if (converter2Length > converter1Length) {
          return converter1;
        } else {
          /*
           * Both have the same lossiness and same length.
           * Arbitrary pick the first.
           */
          return converter1;
        }
      }
    }

    private int determineQuality(String lossiness) {
      if (lossiness == LOSSY) {
        return 0;
      } else if (lossiness == null) {
        return 1;
      // Lossiness == LOSSLESS.
      } else {
        return 2;
      }
    }

    private Converter[] alphabetizeConverters(Converter[] converters) {
      Arrays.sort(converters, new CompareAlphabetically());

      return converters;
    }

    /**
     * When a Persister is chosen to Persist this model, this method handles the job
     * of opening the FileSaver and saving the model.
     * @param selectedIndex The chosen converter.
     */
    protected void selectionMade(int selectedIndex) {
      try {
          getShell().setVisible(false);
          final Converter converter = converters[selectedIndex];
          final FileSaver saver = new FileSaver(getShell(), ciShellContext);
          close(saver.save(converter, data));
      } catch (Exception exception) {
          throw new RuntimeException(exception);
        }
    }

    /**
     * Create the buttons for either cancelling or continuing with the save.
     *
     * @param parent The GUI to place the buttons.
     */
    public void createDialogButtons(Composite parent) {
        Button select = new Button(parent, SWT.PUSH);
        select.setText("Select");
        select.addSelectionListener(
          new SelectionAdapter() {
                public void widgetSelected(SelectionEvent selectionEvent) {
                    int index = converterListComponent.getSelectionIndex();

                    if (index != -1) {
                        selectionMade(index);
                    }
                }
            }
        );
        select.setFocus();

        Button cancel = new Button(parent, SWT.NONE);
        cancel.setText("Cancel");
        cancel.addSelectionListener(
          new SelectionAdapter() {
                public void widgetSelected(SelectionEvent selectionEvent) {
                    close(false);
                }
            }
        );
    }

    /**
     * Checks for the number of file savers.  If there is one converter then it will save directly,
     *  otherwise initialize the chooser.
     *
     * @param parent The parent GUI for new dialog windows.
     */
    public Composite createContent(Composite parent) {
      if (converters.length == 1) {
            final FileSaver saver = new FileSaver((Shell) parent, ciShellContext);
            close(saver.save(converters[0], data));

            return parent;
      }
      else {
        return initializeGUI(parent);
      }
    }
   
    private class CompareAlphabetically implements Comparator {
      public int compare(Object object1, Object object2) {
      if ((object1 instanceof Converter) && (object2 instanceof Converter)) {
        Converter converter1 = (Converter)object1;
        String converter1Label = getLabel(converter1);
       
        Converter converter2 = (Converter)object2;
        String converter2Label = getLabel(converter2);
       
        if ((converter1Label != null) && (converter2Label != null)) {
          return converter1Label.compareTo(converter2Label);
        } else if (converter1Label == null) {
          return 1;
        } else if (converter2Label == null) {
          return -1;
        } else {
          return 0;
        }
      } else {
        throw new IllegalArgumentException("Can only compare Converters");
      }
      }

    private String getLabel(Converter converter) {
      String label = "";
            ServiceReference[] serviceReferences = converter.getConverterChain();

            if ((serviceReferences != null) && (serviceReferences.length > 0)) {
                label = (String)serviceReferences[serviceReferences.length - 1].getProperty(
                  AlgorithmProperty.LABEL);
            }
           
            return label;
    }
    }
}
TOP

Related Classes of org.cishell.reference.gui.persistence.save.SaveDataChooser$CompareAlphabetically

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.