| /******************************************************************************* |
| * 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.editors; |
| |
| import org.eclipse.jface.text.ITextSelection; |
| import org.eclipse.jface.viewers.ISelection; |
| import org.eclipse.jface.viewers.ISelectionChangedListener; |
| import org.eclipse.jface.viewers.SelectionChangedEvent; |
| import org.eclipse.jst.pagedesigner.utils.SelectionHelper; |
| import org.eclipse.swt.custom.StyledText; |
| |
| /** |
| * This class handles selection synchronization between the designer and other |
| * parts. It listens event from both ViewerSelectionManager and the |
| * IDesignerView, and convert the events to each other. |
| * <p> |
| * SelectionSynchronizer will be registered on the ViewerSelectionManager, |
| * basically listens to selection change of other parts, and make the designer |
| * sync with them. |
| * <p> |
| * As ViewerSelectionManager is firing out both textSelectionChange and |
| * nodeSelectionChange, we only need to listen to one of them. As |
| * textSelectionChange provide more information than nodeSelectionChange, so |
| * we'll listen only to textSelectionChange. |
| * |
| * @author mengbo |
| * @version 1.5 |
| */ |
| public class SelectionSynchronizer implements ISelectionChangedListener { |
| private boolean _firingChange = false; |
| |
| private SimpleGraphicalEditor _editor; |
| |
| /** |
| * @param editor |
| */ |
| public SelectionSynchronizer(SimpleGraphicalEditor editor) { |
| _editor = editor; |
| } |
| |
| /** |
| * @return true if the status check is okay |
| */ |
| protected boolean statusCheckOk() { |
| try { |
| StyledText text = _editor.getHTMLEditor().getTextEditor() |
| .getTextViewer().getTextWidget(); |
| if (text == null || text.isDisposed()) { |
| return false; |
| } |
| return true; |
| } catch (NullPointerException ex) { |
| return false; |
| } |
| } |
| |
| /** |
| * This is for event from the designer. |
| */ |
| public void selectionChanged(SelectionChangedEvent event) { |
| ISelection selection = event.getSelection(); |
| |
| if (!_firingChange) { |
| // check current status |
| if (!statusCheckOk()) { |
| return; |
| } |
| |
| _firingChange = true; |
| try { |
| // convert the designer selection into SSE selection |
| // (IStructureSelection of nodes |
| // or textSelection, and let the ViewerSelectionManager to |
| // handle it. |
| // if (selection instanceof IStructuredSelection) |
| // { |
| // IStructuredSelection nodeSel = |
| // SelectionHelper.convertFromDesignSelection((IStructuredSelection)selection); |
| // can't use DoubleClickEvent, since it requre a Viewer. |
| // _viewerSelectionManager.doubleClick(new |
| // DoubleClickEvent(null, nodeSel)); |
| // } |
| // else if (selection instanceof DesignRange) |
| // { |
| // ITextSelection srcselection = |
| // SelectionHelper.convertFromDesignSelection((DesignRange)selection); |
| // event = new SelectionChangedEvent(_editor.getGraphicViewer(), |
| // srcselection); |
| // _viewerSelectionManager.selectionChanged(event); |
| // } |
| ITextSelection srcselection = SelectionHelper |
| .convertFromDesignSelectionToTextSelection(selection); |
| |
| // ideally, we should let the text editor display the selection |
| // through calls to _viewerSelectionManager, |
| // but seemed _viewerSelectionManager don't support that, so we |
| // do workaround by calling the text editor (lium) |
| _editor.getHTMLEditor().getTextEditor().selectAndReveal( |
| srcselection.getOffset(), srcselection.getLength()); |
| } finally { |
| _firingChange = false; |
| } |
| } |
| } |
| |
| /** |
| * We are listening to the selection change in ViewerSelectionManager. The |
| * original source of the event could be source view or the outline view or |
| * other party that participate in the ViewerSelectionManager. |
| * @param start |
| * @param end |
| */ |
| public void textSelectionChanged(int start, int end) { |
| if (!_firingChange) { |
| try { |
| _firingChange = true; |
| |
| // XXX: workaround a SSE problem. In SSE, when user select a |
| // range, it will fire two textSelectionChange event |
| // the first one indicate the correct range, the second one is |
| // zero size for caret position. |
| // @see ViewerSelectionManagerImpl.caretMoved |
| // We try to ignore the second event by checking whether the |
| // current real selection is empty |
| if (start == end) { |
| ITextSelection sel = (ITextSelection) _editor |
| .getHTMLEditor().getTextEditor() |
| .getSelectionProvider().getSelection(); |
| if (sel.getLength() != 0) { |
| return; |
| } |
| } |
| |
| if (start > end) { |
| int temp = start; |
| start = end; |
| end = temp; |
| } |
| int offset = start; |
| int length = end - start; |
| |
| ITextSelection oldSelection = SelectionHelper |
| .convertFromDesignSelectionToTextSelection(_editor |
| .getGraphicViewer().getSelection()); |
| if (oldSelection != null && oldSelection.getOffset() == offset |
| && oldSelection.getLength() == length) { |
| return; |
| } |
| |
| ISelection selection = SelectionHelper |
| .convertToDesignerSelection(this._editor |
| .getGraphicViewer(), offset, length); |
| _editor.getGraphicViewer().setSelection(selection); |
| } finally { |
| _firingChange = false; |
| } |
| } |
| } |
| } |