Package org.locationtech.udig.image.georeferencing.internal.ui.coordinatepanel

Source Code of org.locationtech.udig.image.georeferencing.internal.ui.coordinatepanel.CoordinateTableComposite

/* Image Georeferencing
*
* Axios Engineering
*      http://www.axios.es
*
* (C) 2011, Axios Engineering S.L. (Axios)
*
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* (http://www.eclipse.org/legal/epl-v10.html), and the Axios BSD
* License v1.0 (http://udig.refractions.net/files/asd3-v10.html).
*/
package org.locationtech.udig.image.georeferencing.internal.ui.coordinatepanel;

import java.util.Iterator;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Observable;
import java.util.Observer;
import java.util.Set;

import org.locationtech.udig.project.IMap;
import org.locationtech.udig.project.internal.Layer;
import org.locationtech.udig.project.internal.impl.EditManagerImpl;
import org.locationtech.udig.project.render.IViewportModel;
import org.locationtech.udig.project.ui.ApplicationGIS;
import org.locationtech.udig.project.ui.tool.IToolContext;
import org.locationtech.udig.project.ui.tool.Tool;

import org.eclipse.jface.resource.ImageDescriptor;
import org.eclipse.jface.resource.ImageRegistry;
import org.eclipse.swt.SWT;
import org.eclipse.swt.custom.CLabel;
import org.eclipse.swt.custom.TableEditor;
import org.eclipse.swt.events.ControlAdapter;
import org.eclipse.swt.events.ControlEvent;
import org.eclipse.swt.events.KeyEvent;
import org.eclipse.swt.events.KeyListener;
import org.eclipse.swt.events.ModifyEvent;
import org.eclipse.swt.events.ModifyListener;
import org.eclipse.swt.events.SelectionAdapter;
import org.eclipse.swt.events.SelectionEvent;
import org.eclipse.swt.graphics.Point;
import org.eclipse.swt.graphics.Rectangle;
import org.eclipse.swt.layout.GridData;
import org.eclipse.swt.layout.GridLayout;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Control;
import org.eclipse.swt.widgets.Event;
import org.eclipse.swt.widgets.Listener;
import org.eclipse.swt.widgets.ScrollBar;
import org.eclipse.swt.widgets.Table;
import org.eclipse.swt.widgets.TableColumn;
import org.eclipse.swt.widgets.TableItem;
import org.eclipse.swt.widgets.Text;
import org.eclipse.swt.widgets.ToolBar;
import org.eclipse.swt.widgets.ToolItem;
import org.opengis.referencing.crs.CoordinateReferenceSystem;

import com.vividsolutions.jts.geom.Coordinate;

import org.locationtech.udig.image.georeferencing.internal.i18n.Messages;
import org.locationtech.udig.image.georeferencing.internal.process.MarkModel;
import org.locationtech.udig.image.georeferencing.internal.process.MarkModel.MarkModelChange;
import org.locationtech.udig.image.georeferencing.internal.ui.GeoReferencingCommand;
import org.locationtech.udig.image.georeferencing.internal.ui.GeoReferencingComposite;
import org.locationtech.udig.image.georeferencing.internal.ui.GeoreferencingCommandEventChange;
import org.locationtech.udig.image.georeferencing.internal.ui.InputEvent;
import org.locationtech.udig.image.georeferencing.internal.ui.MainComposite;
import org.locationtech.udig.image.georeferencing.internal.ui.MouseSelectionListener;
import org.locationtech.udig.image.georeferencing.internal.ui.coordinatepanel.tools.AddCoordinateTool;
import org.locationtech.udig.image.georeferencing.internal.ui.coordinatepanel.tools.CapturedCoordinateListener;
import org.locationtech.udig.image.georeferencing.internal.ui.coordinatepanel.tools.CoordToolPropertyValue;
import org.locationtech.udig.image.georeferencing.internal.ui.coordinatepanel.tools.DeleteCoordinateTool;
import org.locationtech.udig.image.georeferencing.internal.ui.coordinatepanel.tools.DeletedCoordinateListener;
import org.locationtech.udig.image.georeferencing.internal.ui.coordinatepanel.tools.MoveCoordinateListener;
import org.locationtech.udig.image.georeferencing.internal.ui.coordinatepanel.tools.MoveCoordinateTool;
import org.locationtech.udig.image.georeferencing.internal.ui.message.InfoMessage;
import org.locationtech.udig.image.georeferencing.internal.ui.message.InfoMessage.Type;

/**
* Composite responsible of managing the mark model coordinates edit operations
* with the aid of tools that interact with the map and a table to directly edit
* them.
*
* It's also an observer of the {@link GeoReferencingCommand} and
* {@link MarkModel}.
*
* @author Mauricio Pazos (www.axios.es)
* @author Aritz Davila (www.axios.es)
* @since 1.3.3
*
*/
public final class CoordinateTableComposite extends Composite implements Observer, GeoReferencingComposite {

  private CLabel              crsLabel        = null;
  private CLabel              mapLabel;
  private Table              coordinatesTable    = null;

  private Composite            compositeGridCoord    = null;
  private GeoReferencingCommand      cmd            = null;
  private IToolContext          toolContext        = null;

  private TableColumn            tableColumnX      = null;
  private TableColumn            tableColumnY      = null;
  private TableColumn            tableColumnID      = null;
  private TableEditor            editorX          = null;
  private TableEditor            editorY          = null;

  @SuppressWarnings("unused")
  private Thread              uiThread        = null;

  private CapturedCoordinateListener    capturedListener    = null;
  private DeletedCoordinateListener    deletedListener      = null;
  private MoveCoordinateListener      moveListener      = null;

  private MouseSelectionListener      mapSelectionListener  = null;
  private MouseSelectionListener      imageSelectionListener  = null;

  private AddCoordinateTool        addTool        = null;
  private DeleteCoordinateTool      deleteTool        = null;
  private MoveCoordinateTool        moveTool        = null;

  private ToolBar              mapToolBar        = null;
  private ImageRegistry          registry        = null;

  private List<MouseSelectionListener>  listeners        = new LinkedList<MouseSelectionListener>();
  private ToolItem            itemDeleteAll;

  /**
   * Constructor method.
   *
   * @param cmd
   *            The georeferencing command.
   * @param parent
   *            The parent composite.
   * @param style
   *            The style.
   */
  public CoordinateTableComposite(GeoReferencingCommand cmd, Composite parent, int style) {

    super(parent, style);

    assert cmd != null;
    this.cmd = cmd;
    createContent();
  }

  private void createContent() {

    this.registry = createImageRegistry();
    this.uiThread = Thread.currentThread();

    createListeners();
    setCoordinateTools();

    GridLayout gridLayout2 = new GridLayout();
    gridLayout2.numColumns = 2;
    gridLayout2.makeColumnsEqualWidth = true;

    compositeGridCoord = new Composite(this, SWT.BORDER);
    compositeGridCoord.setLayout(gridLayout2);

    createCRSselector(compositeGridCoord);
    createToolbar(compositeGridCoord);
    createGrid(compositeGridCoord);
  }

  /**
   * Creates the required listeners, the majority of them are tool listeners.
   */
  private void createListeners() {

    this.capturedListener = new CapturedCoordinateListener() {

      public void capturedCoordinate(Coordinate newCoord) {

        addCoordinateFromMapToTable(newCoord);

        assert getMainComposite().getMapMarkGraphic() != null;
        getMainComposite().refreshMapGraphicLayer();
      }

      public void activated(boolean active) {
      }
    };

    this.deletedListener = new DeletedCoordinateListener() {

      public void deletedCoordinate(java.awt.Point point, InputEvent event) {

        deleteFromTable(point, event);

        // feedback to show the removed coordinate
        assert getMainComposite().getMapMarkGraphic() != null;
        getMainComposite().refreshMapGraphicLayer();
      }

      public void activated(boolean active) {
      }

    };

    this.moveListener = new MoveCoordinateListener() {

      public void MoveCoordinate(java.awt.Point coor, InputEvent event) {

        moveFromTable(coor, event);

        // feedback to show the removed coordinate
        assert getMainComposite().getMapMarkGraphic() != null;
        getMainComposite().refreshMapGraphicLayer();
      }

      public void activated(boolean active) {
      }
    };

    this.mapSelectionListener = new MouseSelectionListener() {

      public void inEvent(MarkModel mark) {

        selectRow(mark);
      }

      public void outEvent(MarkModel mark) {

        deselectRow(mark);
      }
    };

    this.imageSelectionListener = new MouseSelectionListener() {

      public void inEvent(MarkModel mark) {

        selectRow(mark);
      }

      public void outEvent(MarkModel mark) {

        deselectRow(mark);
      }
    };
  }

  /**
   * Creates the {@link ImageRegistry} that stores the image shown by the
   * tools.
   *
   * @return The imageRegistry.
   */
  private ImageRegistry createImageRegistry() {

    ImageRegistry registry = new ImageRegistry(this.getDisplay());

    String opId = "Delete"; //$NON-NLS-1$
    String imgFile = "image/delete.gif"; //$NON-NLS-1$
    registry.put(opId, ImageDescriptor.createFromFile(CoordinateTableComposite.class, imgFile));

    opId = "Add"; //$NON-NLS-1$
    imgFile = "image/add.png"; //$NON-NLS-1$
    registry.put(opId, ImageDescriptor.createFromFile(CoordinateTableComposite.class, imgFile));

    opId = "Move"; //$NON-NLS-1$
    imgFile = "image/movemarker.png"; //$NON-NLS-1$
    registry.put(opId, ImageDescriptor.createFromFile(CoordinateTableComposite.class, imgFile));

    opId = "DeleteAll"; //$NON-NLS-1$
    imgFile = "image/deleteAll.gif"; //$NON-NLS-1$
    registry.put(opId, ImageDescriptor.createFromFile(CoordinateTableComposite.class, imgFile));

    return registry;
  }

  /**
   * Gets a reference to the tools and add the listeners.
   */
  private void setCoordinateTools() {

    Tool tool = ApplicationGIS.getToolManager().findTool(AddCoordinateTool.ID);
    this.addTool = (AddCoordinateTool) tool;
    this.addTool.addCapturedCoordinateListener(capturedListener);

    tool = ApplicationGIS.getToolManager().findTool(DeleteCoordinateTool.ID);
    this.deleteTool = (DeleteCoordinateTool) tool;
    this.deleteTool.addDeletedCoordinateListener(deletedListener);

    tool = ApplicationGIS.getToolManager().findTool(MoveCoordinateTool.ID);
    this.moveTool = (MoveCoordinateTool) tool;
    this.moveTool.addMoveCoordinateListener(moveListener);
  }

  private void createCRSselector(Composite parent) {

    GridData gridData = new GridData();
    gridData.horizontalAlignment = GridData.FILL;
    gridData.grabExcessHorizontalSpace = true;
    gridData.grabExcessVerticalSpace = false;
    gridData.horizontalSpan = 1;
    gridData.verticalAlignment = GridData.FILL;

    mapLabel = new CLabel(parent, SWT.NONE);
    mapLabel.setText(Messages.CoordinateTableComposite_map);
    mapLabel.setLayoutData(gridData);

    crsLabel = new CLabel(parent, SWT.NONE);
    crsLabel.setText("CRS:"); //$NON-NLS-1$
    crsLabel.setLayoutData(gridData);
  }

 
  /**
   * Creates the toolbar that contains the tools that interact with the map.
   *
   * @param parent
   *            The parent composite.
   */
  private void createToolbar(Composite parent) {

    GridData gridData = new GridData();
    gridData.horizontalAlignment = GridData.FILL;
    gridData.grabExcessHorizontalSpace = true;
    gridData.grabExcessVerticalSpace = false;
    gridData.horizontalSpan = 2;
    gridData.verticalAlignment = GridData.FILL;

    mapToolBar = new ToolBar(parent, SWT.LEFT_TO_RIGHT);

    itemDeleteAll = new ToolItem(mapToolBar, SWT.PUSH);
    itemDeleteAll.setImage(this.registry.get("DeleteAll")); //$NON-NLS-1$
    itemDeleteAll.setToolTipText(Messages.CoordinateTableComposite_itemDeleteAll_Tooltip);
    itemDeleteAll.addListener(SWT.Selection, new Listener() {

      public void handleEvent(Event event) {

        deleteAllGCP();
      }
    });

    setItemsEnabled(false);
    setCertainItemsEnabled(false);

    // present the coordinate tools in the tool panel
    CoordToolPropertyValue.setVisible(true);
  }

  private void setItemsEnabled(boolean enabled) {

  }

  private void setCertainItemsEnabled(boolean enabled) {

    itemDeleteAll.setEnabled(enabled);

    if (!enabled) {
      itemDeleteAll.setSelection(false);
    }
  }

  private void createGrid(final Composite parent) {

    GridData gridData = new GridData();
    gridData.horizontalAlignment = GridData.FILL;
    gridData.grabExcessHorizontalSpace = true;
    gridData.grabExcessVerticalSpace = true;
    gridData.horizontalSpan = 2;
    gridData.verticalAlignment = GridData.FILL;

    coordinatesTable = new Table(parent, SWT.BORDER | SWT.SINGLE | SWT.H_SCROLL | SWT.V_SCROLL | SWT.FULL_SELECTION
          | SWT.HIDE_SELECTION);
    coordinatesTable.setHeaderVisible(true);
    coordinatesTable.setLayoutData(gridData);
    coordinatesTable.setLinesVisible(true);

    tableColumnID = new TableColumn(coordinatesTable, SWT.NONE);
    tableColumnID.setWidth(45);
    tableColumnID.setText("ID"); //$NON-NLS-1$
    tableColumnID.setMoveable(true);
    tableColumnID.setResizable(true);

    tableColumnX = new TableColumn(coordinatesTable, SWT.NONE);
    tableColumnX.setText("X"); //$NON-NLS-1$
    tableColumnX.setMoveable(true);
    tableColumnX.setResizable(true);

    tableColumnY = new TableColumn(coordinatesTable, SWT.NONE);
    tableColumnY.setText("Y"); //$NON-NLS-1$
    tableColumnY.setMoveable(true);
    tableColumnY.setResizable(true);

    parent.addControlListener(new ControlAdapter() {
      @Override
      public void controlResized(ControlEvent e) {
        Rectangle area = parent.getClientArea();
        Point size = coordinatesTable.computeSize(SWT.DEFAULT, SWT.DEFAULT);
        ScrollBar vBar = coordinatesTable.getVerticalBar();
        int width = area.width - coordinatesTable.computeTrim(0, 0, 0, 0).width - vBar.getSize().x;
        if (size.y > area.height + coordinatesTable.getHeaderHeight()) {
          // Subtract the scrollbar width from the total column width
          // if a vertical scrollbar will be required
          Point vBarSize = vBar.getSize();
          width -= vBarSize.x;
        }
        Point oldSize = coordinatesTable.getSize();
        if (oldSize.x > area.width) {
          // table is getting smaller so make the columns
          // smaller first and then resize the table to
          // match the client area width
          tableColumnX.setWidth(width / 3);
          tableColumnY.setWidth(width - tableColumnX.getWidth());
          coordinatesTable.setSize(area.width, area.height);
        } else {
          // table is getting bigger so make the table
          // bigger first and then make the columns wider
          // to match the client area width
          coordinatesTable.setSize(area.width, area.height);
          tableColumnX.setWidth(width / 3);
          tableColumnY.setWidth(width - tableColumnX.getWidth());
        }
      }
    });

    editorX = new TableEditor(coordinatesTable);
    // The editor must have the same size as the cell and must
    // not be any smaller than 50 pixels.
    editorX.horizontalAlignment = SWT.LEFT;
    editorX.grabHorizontal = true;
    editorX.minimumWidth = 50;

    editorY = new TableEditor(coordinatesTable);
    // The editor must have the same size as the cell and must
    // not be any smaller than 50 pixels.
    editorY.horizontalAlignment = SWT.LEFT;
    editorY.grabHorizontal = true;
    editorY.minimumWidth = 50;

    coordinatesTable.addSelectionListener(new SelectionAdapter() {
      @Override
      public void widgetSelected(SelectionEvent e) {
        // Clean up any previous editor control
        deleteOldEditors();

        // Identify the selected row
        final TableItem item = (TableItem) e.item;
        if (item == null)
          return;
        // get the mark associated to this row.
        final MarkModel mark = (MarkModel) item.getData();

        createEditorColumnX(mark, item);

        createEditorColumnY(mark, item);
        // show feedback using listeners
        broadcastSelectionInEvent(mark);

        getMainComposite().refreshMapGraphicLayer();
      }
    });
  }

  /**
   * Creates the column editor to edit the X coordinate values.
   *
   * @param mark
   *            Associated mark model
   * @param item
   *            Table item.
   */
  private void createEditorColumnX(final MarkModel mark, final TableItem item) {

    // The control that will be the editor must be a child of the
    // Table
    final Text editorColumnX = new Text(coordinatesTable, SWT.NONE);
    if (mark != null && !(mark.getXCoord().equals(Double.NaN))) {

      editorColumnX.setText(String.valueOf(mark.getXCoord()));
    }
    editorColumnX.addModifyListener(new ModifyListener() {
      public void modifyText(ModifyEvent e) {

        Text text = (Text) editorX.getEditor();
        String newText = text.getText();
        if (mark != null) {
          try {
            // first, try to parse the text into double
            Double value = Double.parseDouble(newText);
            mark.setXCoord(value);
            cmd.evalPrecondition();
            getMainComposite().refreshMapGraphicLayer();
          } catch (NumberFormatException ex) {
            if (newText.equals("")) { //$NON-NLS-1$
              mark.setXCoord(Double.NaN);
            } else {
              newText = String.valueOf(mark.getXCoord());
            }
            cmd.evalPrecondition();
            getMainComposite().refreshMapGraphicLayer();
          }
        }
        item.setText(1, newText);
      }
    });
    editorColumnX.addKeyListener(new KeyListener() {

      public void keyReleased(KeyEvent e) {
        // not used
      }

      public void keyPressed(KeyEvent e) {

        try {
          validateCharacter(e);
        } catch (NumberFormatException ex) {
          e.doit = false;
        }
      }
    });
    editorColumnX.selectAll();
    editorColumnX.setFocus();
    editorX.setEditor(editorColumnX, item, 1);
  }

  /**
   * Creates the column editor to edit the Y coordinate values.
   *
   * @param mark
   *            Associated mark model
   * @param item
   *            Table item.
   */
  private void createEditorColumnY(final MarkModel mark, final TableItem item) {

    final Text editorColumnY = new Text(coordinatesTable, SWT.NONE);
    if (mark != null && !(mark.getYCoord().equals(Double.NaN))) {
      editorColumnY.setText(String.valueOf(mark.getYCoord()));
    }
    editorColumnY.addModifyListener(new ModifyListener() {
      public void modifyText(ModifyEvent e) {

        Text text = (Text) editorY.getEditor();
        String newText = text.getText();
        if (mark != null) {
          try {
            // first, try to parse the text into double
            Double value = Double.parseDouble(newText);
            mark.setYCoord(value);
            cmd.evalPrecondition();
            getMainComposite().refreshMapGraphicLayer();
          } catch (NumberFormatException ex) {
            if (newText.equals("")) { //$NON-NLS-1$
              mark.setYCoord(Double.NaN);
            } else {
              newText = String.valueOf(mark.getYCoord());
            }
            cmd.evalPrecondition();
            getMainComposite().refreshMapGraphicLayer();
          }
        }
        item.setText(2, newText);
      }
    });
    editorColumnY.addKeyListener(new KeyListener() {

      public void keyReleased(KeyEvent e) {
        // not used
      }

      public void keyPressed(KeyEvent e) {

        try {
          validateCharacter(e);
        } catch (NumberFormatException ex) {
          e.doit = false;
        }
      }
    });
    editorY.setEditor(editorColumnY, item, 2);
  }

  /**
   * Delete old editors from the coordinate table.
   */
  private void deleteOldEditors() {

    Control oldEditorX = editorX.getEditor();
    if (oldEditorX != null)
      oldEditorX.dispose();

    Control oldEditorY = editorY.getEditor();
    if (oldEditorY != null)
      oldEditorY.dispose();
  }

  /**
   * Listen to the changes occurred to the command and to the mark model.
   */
  public void update(Observable obs, Object arg) {

    if (obs instanceof GeoReferencingCommand) {

      setCertainItemsEnabled(cmd.canEnableMapTools());

      GeoreferencingCommandEventChange cmdEvent = (GeoreferencingCommandEventChange) arg;
      MarkModel mark = cmdEvent.getMark();

      switch (cmdEvent.getEvent()) {
      case MARK_ADDED:
        addMarkOnTable(mark);
        break;
      case MARK_DELETED:
        deleteMarkOnTable(mark);
        break;
      case ALL_MARKS_DELETED:
        deleteAllMarksOnTable();
        break;
      default:
        break;
      }

    } else if (obs instanceof MarkModel) {

      MarkModel mark = (MarkModel) obs;
      MarkModelChange event = (MarkModelChange) arg;
      switch (event) {
      case MODIFY:
        modifyCoordinateOnTable(mark);
        break;

      default:
        break;
      }
    }

  }

  /**
   * Find the row that contains a reference to this mark model and update the
   * values of that row.
   *
   * @param mark
   *            The mark model.
   */
  private void modifyCoordinateOnTable(MarkModel mark) {

    boolean selection = false;
    TableItem[] selectedItems = coordinatesTable.getSelection();
    if (selectedItems.length > 0) {
      selection = true;
    }
    // find the row.
    TableItem[] items = coordinatesTable.getItems();
    for (TableItem item : items) {

      MarkModel compareMark = (MarkModel) item.getData();
      if (mark.equals(compareMark)) {

        Coordinate newCoord = new Coordinate(mark.getXCoord(), mark.getYCoord());
        if (selection && selectedItems[0].equals(item)) {
          // the selected item is the one to update
          createEditorsAndSetText(mark, item, newCoord);
        }

        setRowData(item, mark, newCoord);
      }
    }

  }

  /**
   * Creates the table editors and set the current value.
   *
   * @param mark
   *            MarkModel model.
   * @param item
   *            Table item.
   * @param newCoord
   *            Coordinate with the values.
   */
  private void createEditorsAndSetText(MarkModel mark, TableItem item, Coordinate newCoord) {

    deleteOldEditors();
    createEditorColumnX(mark, item);
    createEditorColumnY(mark, item);

    Text textX = (Text) editorX.getEditor();
    Text textY = (Text) editorY.getEditor();
    if (!(Double.isNaN(newCoord.x))) {
      textX.setText(String.valueOf(newCoord.x));
    }
    if (!(Double.isNaN(newCoord.y))) {
      textY.setText(String.valueOf(newCoord.y));
    }

  }

  /**
   * <p>
   * Adds a mark to the table.
   *
   * Creates a {@link MarkMapPresenterImp} and associates it with the
   * {@link MapMarksGraphics}.
   * </p>
   *
   * @param mark
   *            Mark model.
   */
  private void addMarkOnTable(MarkModel mark) {

    final TableItem tableItem = new TableItem(coordinatesTable, SWT.NONE);

    // set the mark data to this entire row.
    tableItem.setData(mark);
    tableItem.setText(0, String.valueOf(mark.getID()));

    if (!mark.getXCoord().equals(Double.NaN)) {
      tableItem.setText(1, String.valueOf(mark.getXCoord()));
    }
    if (!mark.getYCoord().equals(Double.NaN)) {
      tableItem.setText(2, String.valueOf(mark.getYCoord()));
    }

    // if a previous row is selected, select the new created row.
    updateRowSelection(tableItem, mark);

    assert getMainComposite().getMapMarkGraphic() != null;

    // create the MarkMapGraphics associated to this mark
    MarkMapPresenter markPresenter = new MarkMapPresenterImp(mark);
    getMainComposite().getMapMarkGraphic().addMarkMapPresenter(markPresenter);

    setItemsEnabled(true);

    mark.addObserver(this);
  }

  /**
   * Given the next scenario:
   *
   * <pre>
   * - New row added
   * - There was a previous row selected.
   * </pre>
   *
   * Update the selected row so it'll select the newly created row.
   *
   * @param tableItem
   *            Table item.
   * @param mark
   *            Mark model.
   */
  private void updateRowSelection(TableItem addedItem, MarkModel mark) {

    TableItem[] selection = coordinatesTable.getSelection();

    if (selection.length > 0) {

      // get the new item
      coordinatesTable.setSelection(addedItem);

      deleteOldEditors();

      createEditorColumnX(mark, addedItem);
      createEditorColumnY(mark, addedItem);
    }
  }

  /**
   * Adds a coordinate to the table.
   *
   * There must be 1 empty row. If there is a selected row and also is empty,
   * then the coordinate will be added there. If there isn't any selected row,
   * the coordinate will be added in the first empty row. If there isn't any
   * empty rows, the coordinate won't be added.
   *
   *
   * @param newCoord
   *            Coordinate to be added.
   */
  private void addCoordinateFromMapToTable(Coordinate newCoord) {

    TableItem[] selection = coordinatesTable.getSelection();

    if (selection.length > 0) {
      // selected item
      // get the row and add the coordinate to that row.
      TableItem item = selection[0];
      addCoordinateOnTable(item, newCoord, true);
    } else {// non selected item
      // get the first empty row and add the coordinate to that row.
      boolean added = false;
      TableItem[] items = coordinatesTable.getItems();
      for (TableItem item : items) {

        added = addCoordinateOnTable(item, newCoord, false);
        // if the coordinate was added, return.
        if (added)
          return;
      }
      // if the code reach this point, the coordinate wasn't added, show
      // an advertise message.
      getMainComposite()
            .setMessage(new InfoMessage(Messages.CoordinateTableComposite_cant_add_gcp, Type.WARNING));
    }
  }

  /**
   * Finds the {@link MainComposite} and returns it.
   *
   * @return The main composite.
   */
  private MainComposite getMainComposite() {

    if (isDisposed()) {
      return null;
    }
    Composite parent = getParent();
    for (;;) {
      if (parent instanceof MainComposite) {
        return (MainComposite) parent;
      } else {
        parent = parent.getParent();
      }
    }
  }

  /**
   * Validate if the given character is a valid integer.
   *
   * @param e
   * @throws NumberFormatException
   *             When the given character isn't an Integer.
   */
  private void validateCharacter(KeyEvent e) throws NumberFormatException {

    if (e.character == '.' || e.keyCode == SWT.DEL || e.keyCode == SWT.BS || e.keyCode == SWT.END
          || e.keyCode == SWT.HOME || e.keyCode == 16777219 || e.keyCode == 16777220 || e.character == '-'
          || e.character == '+') {
      return;
    }

    Integer.parseInt(String.valueOf(e.character));
  }

  /**
   * Delete this mark on the table and refresh the layer that contains the
   * mapGraphic so the changed are shown.
   *
   * @param mark
   *            Mark model to be deleted.
   */
  private void deleteMarkOnTable(MarkModel mark) {

    int index = getMarkIndexWithinTheTable(mark);
    deleteOldEditors();
    coordinatesTable.remove(index);

    getMainComposite().refreshMapGraphicLayer();

    mark.deleteObserver(this);
  }

  /**
   * Find the index of this mark model searching all the table items.
   *
   * @param mark
   *            The mark model.
   * @return The index.
   */
  private int getMarkIndexWithinTheTable(MarkModel mark) {

    int index = -1;
    // find this mark on the table
    TableItem[] items = coordinatesTable.getItems();
    for (TableItem item : items) {
      index++;
      MarkModel itemMark = (MarkModel) item.getData();

      if (mark.equals(itemMark)) {
        break;
      }
    }

    assert index != -1 : "index can't be null, it must have found the given mark."; //$NON-NLS-1$

    return index;
  }

  /**
   * Delete all the marks from the coordinate table.
   */
  private void deleteAllMarksOnTable() {

    deleteOldEditors();
    TableItem[] items = coordinatesTable.getItems();
    coordinatesTable.remove(0, items.length - 1);

    assert coordinatesTable.getItems().length == 0;

    getMainComposite().getMapMarkGraphic().clear();
  }

  /**
   * Add a coordinate into table when mark associated to this table item
   * doesn't have any coordinate value stored.
   *
   * @param item
   *            Table item
   * @param newCoord
   *            Coordinate to be added.
   * @return True when the coordinate was added into the table.
   */
  private boolean addCoordinateOnTable(TableItem item, Coordinate newCoord, boolean existSelection) {

    MarkModel mark = (MarkModel) item.getData();

    if (existSelection) {

      createEditorsAndSetText(mark, item, newCoord);

      setRowData(item, mark, newCoord);

    } else if (mark.getXCoord().equals(Double.NaN) && mark.getYCoord().equals(Double.NaN)) {
      // if marks are empty.

      setRowData(item, mark, newCoord);
      return true;
    }

    return false;
  }

  /**
   * Set the data of the given coordinate in the mark model and in the table.
   *
   * @param item
   *            Table item.
   * @param mark
   *            MarkModel model.
   * @param newCoord
   *            The coordinate containing the data.
   */
  private void setRowData(TableItem item, MarkModel mark, Coordinate newCoord) {

    if (!(Double.isNaN(newCoord.x))) {
      item.setText(1, String.valueOf(newCoord.x));
    }else{
      item.setText(1, ""); //$NON-NLS-1$
    }
    if (!(Double.isNaN(newCoord.y))) {
      item.setText(2, String.valueOf(newCoord.y));
    }else{
      item.setText(2, ""); //$NON-NLS-1$
    }

    mark.setXCoord(newCoord.x);
    mark.setYCoord(newCoord.y);
    // evaluate preconditions
    this.cmd.evalPrecondition();
  }

  /**
   * The first time, adds the listeners.
   */
  public void setContext(IToolContext newContext) {

    if (this.toolContext == null) {
      // add the listener the first time.
      getMainComposite().getMapMarkGraphic().addMouseSelectionListener(mapSelectionListener);
      getMainComposite().addMouseSelectionListenerToImgComposite(imageSelectionListener);
    }
    this.toolContext = newContext;

    if (toolContext != null) {

      // display the map
      IMap map = toolContext.getMap();
      mapLabel.setText("Map: " + map.getName()); //$NON-NLS-1$
      // display the CRS.
      CoordinateReferenceSystem crs = getCurrentMapCrs(map);
      crsLabel.setText("CRS: " + crs.getName().toString()); //$NON-NLS-1$
    }

  }

  /**
   * @param map
   * @return the current map's CRS or null if current map is null
   */
  private CoordinateReferenceSystem getCurrentMapCrs(IMap map) {
   
        IViewportModel viewportModel = map.getViewportModel();
        CoordinateReferenceSystem mapCrs = viewportModel.getCRS();
    return mapCrs;
  }

  /**
   * Remove all the listeners of the tools and de-activates them.
   *
   * @param mainComposite
   *            The main composite.
   */
  public void close(MainComposite mainComposite) {

    hideCoordinateTools();
   
    // remove the listener
    this.addTool.removeCapturedCoordinateListener(this.capturedListener);
    this.deleteTool.removeDeletedCoordinateListener(this.deletedListener);
    this.moveTool.removeMoveCoordinateListener(this.moveListener);

    this.addTool.setActive(false);
    this.deleteTool.setActive(false);
    this.moveTool.setActive(false);

    if (this.toolContext != null) {// & !isDisposed()) {
      // delete the listener
      mainComposite.getMapMarkGraphic().deleteMouseSelectionListener(mapSelectionListener);
      mainComposite.deleteMouseSelectionListenerToImgComposite(imageSelectionListener);
    }
  }

  /**
   * Hide the coordinate tools
   */
  private void hideCoordinateTools() {
   
    // this is a workaround to provoke an event in the layer view that could be catch by the CoordToolPropertyValue 
    CoordToolPropertyValue.setVisible(false);

    EditManagerImpl editManager = (EditManagerImpl) ApplicationGIS.getActiveMap().getEditManager();
    Layer layer = editManager.getSelectedLayer();
    editManager.setSelectedLayerGen(layer);
  }

  @Override
  public void setEnabled(boolean enabled) {

    this.coordinatesTable.setEnabled(enabled);
    if (this.editorX.getEditor() != null && !this.editorX.getEditor().isDisposed()) {
      this.editorX.getEditor().setEnabled(enabled);
    }
    if (this.editorY.getEditor() != null && !this.editorY.getEditor().isDisposed()) {
      this.editorY.getEditor().setEnabled(enabled);
    }

    setItemsEnabled(enabled);
    setCertainItemsEnabled(enabled);

    super.setEnabled(enabled);
  }

  /**
   * <p>
   * When a mouse_down event occur, gets all the map presenters and search if
   * any of these presenters are affected by the event. If any of the
   * presenter returns true, this mark coordinate data will be deleted from
   * the table and from the mark model.
   *
   * If the event is not a mouse_down, delegates the event to the
   * {@link MapMarksGraphics}.
   * </p>
   *
   * @param point
   *            Map point where it was clicked.
   * @param event
   *            Input event.
   */
  private void deleteFromTable(java.awt.Point point, InputEvent event) {

    if (InputEvent.MOUSE_DOWN.equals(event)) {
      // get the presenters
      Map<String, MarkMapPresenter> presenters = getMainComposite().getMapMarkGraphic().getPresenters();

      // iterate the presenters and see if the point belongs to any mark
      MarkModel mark = null;
      Set<Entry<String, MarkMapPresenter>> entrySet = presenters.entrySet();
      Iterator<Entry<String, MarkMapPresenter>> iter = entrySet.iterator();
      while (iter.hasNext()) {

        Entry<String, MarkMapPresenter> entry = iter.next();
        MarkMapPresenter mapPresenter = entry.getValue();

        if (mapPresenter.eventHandler(InputEvent.DELETE, point.x, point.y)) {
          mark = mapPresenter.getMarkModel();
          break;
        }
      }

      if (mark != null) {

        deleteOldEditors();

        int index = getMarkIndexWithinTheTable(mark);
        TableItem item = coordinatesTable.getItem(index);

        item.setText(1, ""); //$NON-NLS-1$
        item.setText(2, ""); //$NON-NLS-1$

        mark.setXCoord(Double.NaN);
        mark.setYCoord(Double.NaN);

        this.cmd.evalPrecondition();
        getMainComposite().refreshMapGraphicLayer();

      }
    } else {
      getMainComposite().getMapMarkGraphic().eventhandler(event, point);
    }
  }

  /**
   * Delegate the move event to the {@link MapMarksGraphics}.
   *
   * @param point
   *            Map point where it was clicked.
   * @param event
   *            Input event.
   */
  private void moveFromTable(java.awt.Point point, InputEvent event) {

    // the mapMarkGraphics will be the responsible to handle these
    // behaviours
    getMainComposite().getMapMarkGraphic().eventhandler(event, point);
  }

  /**
   * Selects the row corresponding to the given mark.
   *
   * @param mark
   *            MarkModel
   */
  private void selectRow(MarkModel mark) {

    deleteOldEditors();

    int index = getMarkIndexWithinTheTable(mark);
    assert index >= 0;
    coordinatesTable.setSelection(index);

    createEditorColumnX(mark, coordinatesTable.getSelection()[0]);
    createEditorColumnY(mark, coordinatesTable.getSelection()[0]);
  }

  /**
   * If a row is selected and it owns the given mark model, it'll deselect it.
   *
   * @param mark
   *            The mark model.
   */
  private void deselectRow(MarkModel mark) {

    int index = getMarkIndexWithinTheTable(mark);
    int selection = coordinatesTable.getSelectionIndex();
    if (index == selection) {
      coordinatesTable.deselect(selection);
      deleteOldEditors();
    }

  }

  /**
   * Adds a {@link MouseSelectionListener}.
   *
   * @param listener
   *            The listener.
   */
  public void addMouseSelectionListener(MouseSelectionListener listener) {

    listeners.add(listener);
  }

  /**
   * Deletes a {@link MouseSelectionListener}.
   *
   * @param listener
   *            The listener.
   */
  public void deleteMouseSelectionListener(MouseSelectionListener listener) {

    listeners.remove(listener);
  }

  /**
   * Broadcast to all its listeners that the given mark has been selected in
   * the coordinate table.
   *
   * @param mark
   *            The mark model
   */
  private void broadcastSelectionInEvent(MarkModel mark) {

    for (MouseSelectionListener listener : listeners) {
      listener.inEvent(mark);
    }
  }

  private void deleteAllGCP() {

    Coordinate emptyCoord = new Coordinate(Double.NaN, Double.NaN);
    TableItem[] items = this.coordinatesTable.getItems();
    for (TableItem item : items) {
      MarkModel itemMark = (MarkModel) item.getData();
      itemMark.updateCoordinatePosition(emptyCoord);
     
    }
    getMainComposite().refreshMapGraphicLayer();
  }
}
TOP

Related Classes of org.locationtech.udig.image.georeferencing.internal.ui.coordinatepanel.CoordinateTableComposite

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.