/* ******************************************************************************
* Copyright (c) 2006-2012 XMind Ltd. and others.
*
* This file is a part of XMind 3. XMind releases 3 and
* above are dual-licensed under the Eclipse Public License (EPL),
* which is available at http://www.eclipse.org/legal/epl-v10.html
* and the GNU Lesser General Public License (LGPL),
* which is available at http://www.gnu.org/licenses/lgpl.html
* See http://www.xmind.net/license.html for details.
*
* Contributors:
* XMind Ltd. - initial API and implementation
*******************************************************************************/
package org.xmind.gef.ui.editor;
import org.eclipse.swt.SWT;
import org.eclipse.swt.custom.CTabFolder;
import org.eclipse.swt.custom.CTabItem;
import org.eclipse.swt.dnd.DND;
import org.eclipse.swt.dnd.DropTarget;
import org.eclipse.swt.dnd.DropTargetAdapter;
import org.eclipse.swt.dnd.DropTargetEvent;
import org.eclipse.swt.dnd.DropTargetListener;
import org.eclipse.swt.dnd.Transfer;
import org.eclipse.swt.events.DisposeEvent;
import org.eclipse.swt.events.DisposeListener;
import org.eclipse.swt.events.PaintEvent;
import org.eclipse.swt.events.PaintListener;
import org.eclipse.swt.graphics.GC;
import org.eclipse.swt.graphics.Point;
import org.eclipse.swt.graphics.Rectangle;
/**
* @author Frank Shaka
*/
public class GraphicalEditorDropPageChangeHelper {
private class PageChangeTask implements Runnable {
private boolean canceled = false;
public void run() {
if (canceled)
return;
changePage();
currentTask = null;
}
public void cancel() {
this.canceled = true;
}
}
private static final int PAGE_CHANGE_DELAY = 1000;
private IGraphicalEditor editor;
private CTabFolder tabFolder;
private DropTarget dropTarget;
private DropTargetListener handler;
private CTabItem currentItem = null;
private PageChangeTask currentTask = null;
public GraphicalEditorDropPageChangeHelper(IGraphicalEditor editor,
CTabFolder tabFolder, int style, Transfer[] acceptableTransfers) {
this.editor = editor;
this.tabFolder = tabFolder;
createDropTarget(style, acceptableTransfers);
}
private void createDropTarget(int style, Transfer[] acceptableTransfers) {
dropTarget = new DropTarget(tabFolder, style);
if (acceptableTransfers != null) {
dropTarget.setTransfer(acceptableTransfers);
}
handler = createHandler();
dropTarget.addDropListener(handler);
hookTabFolder();
}
private void hookTabFolder() {
tabFolder.addPaintListener(new PaintListener() {
public void paintControl(PaintEvent e) {
if (currentItem != null) {
GC gc = e.gc;
if (gc != null) {
gc.setAlpha(0x30);
gc.setBackground(e.display
.getSystemColor(SWT.COLOR_LIST_SELECTION));
//gc.setForeground( tabFolder.getDisplay().getSystemColor( SWT.COLOR_RED ) );
Rectangle r = currentItem.getBounds();
//gc.drawRectangle( r.x, r.y, r.width - 1, r.height - 1 );
gc.fillRectangle(r);
}
}
}
});
tabFolder.addDisposeListener(new DisposeListener() {
public void widgetDisposed(DisposeEvent e) {
dispose();
}
});
}
private DropTargetListener createHandler() {
return new DropTargetAdapter() {
@Override
public void dragOver(DropTargetEvent event) {
CTabItem oldItem = currentItem;
CTabItem newItem = findItem(event.x, event.y);
if (newItem != oldItem) {
cancelUndoneTask();
if (newItem != tabFolder.getSelection()) {
currentItem = newItem;
if (currentItem != null) {
startNewTask();
}
redrawTabFolder();
} else {
currentItem = null;
if (oldItem != null)
redrawTabFolder();
}
}
event.detail = DND.DROP_COPY;
}
@Override
public void dragLeave(DropTargetEvent event) {
cancelUndoneTask();
boolean needRedraw = currentItem != null;
currentItem = null;
if (needRedraw)
redrawTabFolder();
}
};
}
private void startNewTask() {
currentTask = new PageChangeTask();
tabFolder.getDisplay().timerExec(PAGE_CHANGE_DELAY, currentTask);
}
private void redrawTabFolder() {
tabFolder.redraw();
}
private void cancelUndoneTask() {
if (currentTask != null) {
currentTask.cancel();
currentTask = null;
}
}
protected void changePage() {
if (currentItem == null)
return;
int pageIndex = tabFolder.indexOf(currentItem);
editor.setActivePage(pageIndex);
currentItem = null;
redrawTabFolder();
}
private CTabItem findItem(int x, int y) {
Point location = tabFolder.toControl(x, y);
return tabFolder.getItem(location);
}
protected void dispose() {
cancelUndoneTask();
if (dropTarget != null) {
if (handler != null && !dropTarget.isDisposed()) {
dropTarget.removeDropListener(handler);
}
dropTarget.dispose();
}
dropTarget = null;
handler = null;
tabFolder = null;
editor = null;
}
}