Package org.eclipse.jst.pagedesigner.viewer

Source Code of org.eclipse.jst.pagedesigner.viewer.HTMLGraphicalViewer

/*******************************************************************************
* Copyright (c) 2006 Sybase, Inc. and others.
*
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
*     Sybase, Inc. - initial API and implementation
*******************************************************************************/
package org.eclipse.jst.pagedesigner.viewer;

import java.util.ArrayList;
import java.util.List;

import org.eclipse.draw2d.FigureCanvas;
import org.eclipse.draw2d.Viewport;
import org.eclipse.gef.EditPart;
import org.eclipse.gef.ui.parts.ScrollingGraphicalViewer;
import org.eclipse.jface.action.IStatusLineManager;
import org.eclipse.jface.viewers.ISelection;
import org.eclipse.jface.viewers.IStructuredSelection;
import org.eclipse.jst.pagedesigner.commands.nav.CaretPositionTracker;
import org.eclipse.jst.pagedesigner.dom.DOMPositionHelper;
import org.eclipse.jst.pagedesigner.dom.DOMRefPosition;
import org.eclipse.jst.pagedesigner.dom.IDOMPosition;
import org.eclipse.jst.pagedesigner.parts.DocumentEditPart;
import org.eclipse.jst.pagedesigner.parts.ElementEditPart;
import org.eclipse.jst.pagedesigner.tools.ExposeHelper;
import org.eclipse.swt.widgets.Canvas;
import org.eclipse.swt.widgets.Caret;
import org.eclipse.ui.IEditorPart;
import org.eclipse.wst.xml.core.internal.provisional.document.IDOMModel;
import org.eclipse.wst.xml.core.internal.provisional.document.IDOMNode;
import org.w3c.dom.Node;

/**
* For the GraphicalViewer selection management, we have two different selection
* mode: Range mode and object mode.
*
* Range mode is to support inline text editing, it selects a range. Object mode
* selects a list of edit parts.
*
* We let the super class of HTMLGraphicalViewer to handle object selection, and
* add range selection support in this class. Need to override certain selection
* related methods of super class to handle selection mode switching.
*
* @author mengbo
*/
/*package*/ class HTMLGraphicalViewer extends ScrollingGraphicalViewer implements
    IHTMLGraphicalViewer, CaretPositionTracker {
  private IEditorPart _parentPart;
  private Caret _caret;
  // initially nothing selected, treat as object selectin mode.
  private boolean _rangeMode = false;
  private DesignRange _selectionRange = null;
  private int _inBatch = 0;
  private final CaretUpdater _caretUpdater;
  private int _xOffset;
  private final List<IHTMLGraphicalViewerListener>  _htmlViewerListeners;
  // private ListenerList _postSelectionChangedListeners = new
  // ListenerList(1);

  /**
   * @param parent
   *
   */
  public HTMLGraphicalViewer(IEditorPart parent) {
    _parentPart = parent;
    // CaretUpdater is not fully initialized yet, since this time the
    // viewport is not
    // initialized yet, and we need add listener to range model change.
        _htmlViewerListeners = new ArrayList<IHTMLGraphicalViewerListener>();
    _caretUpdater = new CaretUpdater(this);
  }

  /**
   * Adds listener both as a selection changed listener and as an
   * {@link IHTMLGraphicalViewerListener}.  Callers of this method
   * need not call addSelectionChangedListener.
   * @param listener
   */
  public void addHTMLViewerListener(IHTMLGraphicalViewerListener listener)
  {
      addSelectionChangedListener(listener);
     
      if (!_htmlViewerListeners.contains(listener))
      {
          _htmlViewerListeners.add(listener);
      }
  }
 
  /**
   * Removes listener both as a selection changed listener and as an
     * {@link IHTMLGraphicalViewerListener}.  Callers of this method
     * need not call removeSelectionChangedListener.
   * @param listener
   */
  public void removeHTMLViewerListener(IHTMLGraphicalViewerListener listener)
  {
      removeSelectionChangedListener(listener);
      _htmlViewerListeners.remove(listener);
  }

  public Viewport getViewport() {
    FigureCanvas canvas = this.getFigureCanvas();
    if (canvas != null) {
      return canvas.getViewport();
    }
        return null;
  }

  public IDOMModel getModel() {
    // XXX: temp implementation.
    EditPart part = this.getContents();
    if (part != null) {
      return ((IDOMNode) part.getModel()).getModel();
    }
        return null;
  }

  /**
   * @return the status line manager
   */
  public IStatusLineManager getStatusLineManager() {
    if (_parentPart == null) {
      return null;
    }
        return _parentPart.getEditorSite().getActionBars()
            .getStatusLineManager();
  }

  public Caret getCaret() {
    if (_caret == null) {
      Canvas parentCanvas = (Canvas) getControl();
      if (parentCanvas == null || parentCanvas.isDisposed()) {
        return null;
      }

      _caret = new Caret(parentCanvas, 0);
      _caretUpdater.connectViewer();
    }
    return _caret;

  }

  /**
   * this method normally should only be called when in object selection mode.
   *
   * @return the edit part that has primary selection or null if none
   */
  public EditPart getPrimarySelectedNode() {
    List list = this.getSelectedEditParts();
    if (list.isEmpty()) {
      return null;
    }
    for (int i = 0, n = list.size(); i < n; i++) {
      EditPart part = (EditPart) list.get(i);
      if (part.getSelected() == EditPart.SELECTED_PRIMARY) {
        return part;
      }
    }
    return (EditPart) list.get(0);
  }

  /*
   * (non-Javadoc)
   *
   * @see org.eclipse.jst.pagedesigner.parts.IHTMLGraphicalViewer#ensureRangeSelectionMode()
   */
  public void ensureRangeSelectionMode() {
    if (!_rangeMode) {
      EditPart primary = getPrimarySelectedNode();
      this.deselectAll();
      DesignPosition begin = primary == null ? DesignPosition.INVALID
          : DesignPosition.createPositionBeforePart(primary);
      DesignPosition after = primary == null ? DesignPosition.INVALID
          : DesignPosition.createPositionAfterPart(primary);
      internalSetRange(begin, after);
      fireSelectionChanged();
    }
  }

  /*
   * (non-Javadoc)
   *
   * @see org.eclipse.jst.pagedesigner.parts.IHTMLGraphicalViewer#ensureObjectSelectionMode()
   */
  public void ensureObjectSelectionMode() {
    if (_rangeMode) {
      // switch to object selection mode with no selection.
      internalToObjectMode();
      fireSelectionChanged();
    }
  }

  /*
   * (non-Javadoc)
   *
   * @see org.eclipse.jst.pagedesigner.parts.IHTMLGraphicalViewer#isInRangeMode()
   */
  public boolean isInRangeMode() {
    return _rangeMode;
  }

  public ISelection getSelection() {
    if (isInRangeMode()) {
      return getRangeSelection();
    }
        return super.getSelection();
  }

  /*
   * (non-Javadoc)
   *
   * @see org.eclipse.jst.pagedesigner.parts.IHTMLGraphicalViewer#startSelectionChange()
   */
  public void startSelectionChange() {
    if (_inBatch == 0) {
      fireSelectionAboutToChange();
    }
    _inBatch++;
  }

  /*
   * (non-Javadoc)
   *
   * @see org.eclipse.jst.pagedesigner.parts.IHTMLGraphicalViewer#selectionChanged()
   */
  public void selectionChanged() {
    if (--_inBatch == 0) {
      fireSelectionChanged();
      fireSelectionChangeFinished();
    }
  }

  /**
   *
   */
  private void fireSelectionAboutToChange() {
    IHTMLGraphicalViewerListener listeners[] =
        _htmlViewerListeners.toArray(new IHTMLGraphicalViewerListener[0]);

    for (int i = 0; i < listeners.length; i++)
    {
      listeners[i].selectionAboutToChange();
    }
  }

  /**
   *
   */
  private void fireSelectionChangeFinished()
  {
        IHTMLGraphicalViewerListener listeners[] =
            _htmlViewerListeners.toArray(new IHTMLGraphicalViewerListener[0]);
        for (int i = 0; i < listeners.length; i++)
        {
            listeners[i].selectionChangeFinished();
        }
  }

  /*
   * (non-Javadoc)
   *
   * @see org.eclipse.gef.ui.parts.AbstractEditPartViewer#fireSelectionChanged()
   */
  protected void fireSelectionChanged() {
    if (_inBatch == 0)// && this.getControl().isFocusControl())
    {
      super.fireSelectionChanged();
      // firePostSelectionChanged(new SelectionChangedEvent(this,
      // getSelection()));
    }
  }

  /*
   * (non-Javadoc)
   *
   * @see org.eclipse.gef.ui.parts.AbstractEditPartViewer#setSelection(org.eclipse.jface.viewers.ISelection)
   */
  public void setSelection(ISelection newSelection) {
    if (newSelection instanceof IStructuredSelection) {
      internalToObjectMode();
      ExposeHelper.expose(newSelection, this);
      updateRangeSelection(newSelection);
      super.setSelection(newSelection);
    } else if (newSelection instanceof DesignRange) {
      DesignRange range = (DesignRange) newSelection;
      internalSetRange(range.getStartPosition(), range.getEndPosition());
      fireSelectionChanged();
    }
    // else we don't support, ignore
  }


  /**
   * @param newSelection
   */
  public void updateRangeSelection(ISelection newSelection) {
    if (newSelection instanceof IStructuredSelection && //
        !(((IStructuredSelection) newSelection).getFirstElement() instanceof DocumentEditPart)) {
      Object element = ((IStructuredSelection) newSelection)
          .getFirstElement();
      if (element instanceof ElementEditPart) {
        updateRangeSelection(new DesignRefPosition((EditPart) element,
            false), new DesignRefPosition((EditPart) element, true));
      } else if (element instanceof Node) {
        IDOMPosition start = new DOMRefPosition((Node) element, false);
        IDOMPosition end = new DOMRefPosition((Node) element, true);
        updateRangeSelection(DOMPositionHelper.toDesignPosition(start),
            DOMPositionHelper.toDesignPosition(end));
      }
    }
  }

  /**
   * This method is used to synchronize range mode selection when node
   * selection is changed.
   *
   * @param position
   * @param position2
   */
  private void updateRangeSelection(DesignPosition position,
      DesignPosition position2) {
    // if only one position is invalid, we will make a collapsed range using
    // the valid position
    if (position == null) {
      position = DesignPosition.INVALID;
    }
    if (position2 == null || !position2.isValid()) {
      position2 = position;
    }
    if (!position.isValid()) {
      position = position2;
    }

    _selectionRange = new DesignRange(position, position2);
  }

  // -------------------------------------------------------------------------------------------------
  // override super class methods for selection handling.
  // operations that handles object selection
  /*
   * (non-Javadoc)
   *
   * @see org.eclipse.gef.ui.parts.AbstractEditPartViewer#appendSelection(org.eclipse.gef.EditPart)
   */
  public void appendSelection(EditPart editpart) {
    internalToObjectMode();
    super.appendSelection(editpart); // super will fireSelectionChanged.
  }

  /*
   * (non-Javadoc)
   *
   * @see org.eclipse.gef.ui.parts.AbstractEditPartViewer#deselectAll()
   */
  public void deselectAll() {
    internalToObjectMode();
    super.deselectAll(); // super.deselectAll() will fireSelectionChanged
  }

  /**
   * Clear the selection to null. When the model is modified, the selection is
   * invalid, so we need to clear the selection. We change the selection
   * directly, it won't need to fire selectionchange event to other part.
   *
   */
  public void clearSelectionRange() {
    internalToObjectMode();
    _selectionRange = null;
  }

  /*
   * (non-Javadoc)
   *
   * @see org.eclipse.gef.ui.parts.AbstractEditPartViewer#deselect(org.eclipse.gef.EditPart)
   */
  public void deselect(EditPart editpart) {
    if (!_rangeMode) {
      super.deselect(editpart); // super will fireSelectionChanged.
    }
    // else just ignore.
  }

  // ---------------------------------------------------------------------------------------------
  // range selection handling methods.
  /*
   * (non-Javadoc)
   *
   * @see org.eclipse.jst.pagedesigner.parts.IHTMLGraphicalViewer#getRangeSelection()
   */
  public DesignRange getRangeSelection() {
    return _selectionRange;
  }

  /*
   * (non-Javadoc)
   *
   * @see org.eclipse.jst.pagedesigner.parts.IHTMLGraphicalViewer#setRange(org.eclipse.jst.pagedesigner.selection.EditPartPosition,
   *      org.eclipse.jst.pagedesigner.selection.EditPartPosition)
   */
  public void setRange(DesignPosition position, DesignPosition position2) {
    internalSetRange(position, position2);
    fireSelectionChanged();
  }

  /*
   * (non-Javadoc)
   *
   * @see org.eclipse.jst.pagedesigner.parts.IHTMLGraphicalViewer#setRangeEndPosition(org.eclipse.jst.pagedesigner.selection.EditPartPosition)
   */
  public void setRangeEndPosition(DesignPosition position) {
    DesignRange range = getRangeSelection();
    DesignPosition begin = null;
    if (range != null) {
      begin = range.getStartPosition();
    }
    internalSetRange(begin, position);
    fireSelectionChanged();
  }

  // --------------------------------------------------------------------------------------
  /**
   * internall switch to object mode, no selection change event is fired. the
   * caller must call some other methods that will result in selection change
   * event after calling this method.
   */
  private void internalToObjectMode() {
    _rangeMode = false;
  }

  /**
   * this method will not fire selection changed event. caller should do that.
   *
   * @param position
   * @param position2
   */
  private void internalSetRange(DesignPosition position,
      DesignPosition position2) {
    if (!_rangeMode) {
      // XXX: deselectAll() will result in fireSelectionChange, so here is
      // one unnecessary
      // event fire. But should be ok.
      deselectAll();
      _rangeMode = true;
    }
    // if only one position is invalid, we will make a collapsed range using
    // the valid position
    if (position == null) {
      position = DesignPosition.INVALID;
    }
    if (position2 == null || !position2.isValid()) {
      position2 = position;
    }
    if (!position.isValid()) {
      position = position2;
    }

    _selectionRange = new DesignRange(position, position2);
  }

  /**
   * debug method, dump some debug information to the console
   */
  public void dumpStatus() {
    if (isInRangeMode()) {
      // System.out.println("Range start: " +
      // this.getRangeSelection().getStartPosition());
      // System.out.println("Range end: " +
      // this.getRangeSelection().getEndPosition());
    } else {
      // System.out.println("Object selection mode");
    }
  }

  /*
   * (non-Javadoc)
   *
   * @see org.eclipse.jst.pagedesigner.commands.nav.CaretPositionTracker#getXoffset()
   */
  public int getXoffset() {
    return _xOffset;
  }

  /*
   * (non-Javadoc)
   *
   * @see org.eclipse.jst.pagedesigner.commands.nav.CaretPositionTracker#setXoffset(int)
   */
  public void setXoffset(int xoffset) {
    this._xOffset = xoffset;
  }

  /**
   *
   */
  public void updateHorizontalPos() {
    Caret caret = getCaret();
    if (caret != null && !caret.isDisposed() && isInRangeMode()) {
      org.eclipse.swt.graphics.Rectangle rect = caret.getBounds();
      setXoffset(rect.x);
    }
  }
   
  // public void addPostSelectionChangedListener(ISelectionChangedListener
  // listener)
  // {
  // _postSelectionChangedListeners.add(listener);
  //
  // }
  //
  // public void removePostSelectionChangedListener(ISelectionChangedListener
  // listener)
  // {
  // _postSelectionChangedListeners.remove(listener);
  // }

  /**
   * Notifies any post selection listeners that a post selection event has
   * been received. Only listeners registered at the time this method is
   * called are notified.
   *
   * @param event
   *            a selection changed event
   *
   * @see #addPostSelectionChangedListener(ISelectionChangedListener)
   */
  // public void firePostSelectionChanged(final SelectionChangedEvent event)
  // {
  // Object[] listeners = _postSelectionChangedListeners.getListeners();
  // for (int i = 0; i < listeners.length; ++i)
  // {
  // final ISelectionChangedListener l = (ISelectionChangedListener)
  // listeners[i];
  // SafeRunnable.run(new SafeRunnable()
  // {
  // public void run()
  // {
  // l.selectionChanged(event);
  // }
  // });
  // }
  // }
}
TOP

Related Classes of org.eclipse.jst.pagedesigner.viewer.HTMLGraphicalViewer

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.