/*******************************************************************************
* Copyright (c) 2007 Exadel, Inc. and Red Hat, Inc.
* Distributed under license by Red Hat, Inc. All rights reserved.
* This program is 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:
* Exadel, Inc. and Red Hat, Inc. - initial API and implementation
******************************************************************************/
package org.jboss.tools.common.model.ui.views.palette;
import java.io.File;
import java.util.Properties;
import org.eclipse.core.resources.IFile;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.QualifiedName;
import org.eclipse.swt.SWT;
import org.eclipse.swt.custom.ScrolledComposite;
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.FileTransfer;
import org.eclipse.swt.dnd.Transfer;
import org.eclipse.swt.events.ControlAdapter;
import org.eclipse.swt.events.ControlEvent;
import org.eclipse.swt.events.SelectionAdapter;
import org.eclipse.swt.events.SelectionEvent;
import org.eclipse.swt.graphics.Image;
import org.eclipse.swt.graphics.Point;
import org.eclipse.swt.graphics.Rectangle;
import org.eclipse.swt.layout.RowLayout;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Control;
import org.eclipse.swt.widgets.ToolBar;
import org.eclipse.swt.widgets.ToolItem;
import org.eclipse.ui.IActionBars;
import org.eclipse.jface.action.Action;
import org.eclipse.jface.action.ActionContributionItem;
import org.eclipse.jface.action.IAction;
import org.eclipse.jface.action.IContributionItem;
import org.eclipse.jface.action.IMenuManager;
import org.jboss.tools.common.model.XModel;
import org.jboss.tools.common.model.XModelException;
import org.jboss.tools.common.model.XModelObject;
import org.jboss.tools.common.model.event.ActionDeclinedException;
import org.jboss.tools.common.model.event.XModelTreeEvent;
import org.jboss.tools.common.model.event.XModelTreeListener;
import org.jboss.tools.common.model.util.EclipseResourceUtil;
import org.jboss.tools.common.model.util.IconUtil;
import org.jboss.tools.common.model.ui.ModelUIPlugin;
import org.jboss.tools.common.model.ui.dnd.DnDUtil;
import org.jboss.tools.common.model.ui.dnd.ModelTransfer;
import org.jboss.tools.common.model.ui.views.palette.model.*;
import org.jboss.tools.common.model.ui.util.StringUtilities;
public class PaletteAdapter implements IPaletteAdapter {
private static final int TEXT_MARGIN = 4;
private IPalettePageAdapter viewPart = null;
private PaletteModel model = null;
private ScrolledComposite pane = null;
private PaletteModelListener modelListener = null;
private PaletteDescriptionManager descriptionManager = null;
private PaletteResizeManager resizeManager = null;
private PaletteDropTargetManager dropManager = null;
private QualifiedName persistentTabQualifiedName = new QualifiedName("", "Palette_tab"); //$NON-NLS-1$ //$NON-NLS-2$
private String selectedTab = null;
private boolean fWindowsFlag;
public void setPaletteViewPart(IPalettePageAdapter viewPart) {
this.viewPart = viewPart;
}
public void initActionBars() {
IActionBars bars = viewPart.getActionBars();
if(bars != null) {
createPaletteTabs();
IMenuManager menuManager = bars.getMenuManager();
bars.getToolBarManager().add(new PaletteEditAction());
bars.getToolBarManager().add(new ShowHideTabsAction());
if (selectedTab != null) {
ActionContributionItem item = (ActionContributionItem)menuManager.find(selectedTab);
if (item != null) {
item.getAction().run();
}
} else {
IContributionItem[] actions = menuManager.getItems();
if (actions.length > 0 && (actions[0] instanceof ActionContributionItem)) {
((ActionContributionItem)actions[0]).getAction().run();
}
}
}
}
public Control createControl(Composite composite) {
String osName = System.getProperty("os.name"); //$NON-NLS-1$
fWindowsFlag = osName != null && osName.toUpperCase().indexOf("WINDOWS") != -1; //$NON-NLS-1$
try {
selectedTab = ModelUIPlugin.getWorkspace().getRoot().getPersistentProperty(persistentTabQualifiedName);
} catch (CoreException e) {
ModelUIPlugin.getPluginLog().logError(e);
}
pane = new ScrolledComposite(composite, SWT.V_SCROLL);
pane.setExpandHorizontal(true);
pane.setExpandVertical(true);
descriptionManager = new PaletteDescriptionManager();
resizeManager = new PaletteResizeManager();
dropManager = new PaletteDropTargetManager();
model = PaletteModel.getInstance();
createPaletteTabs();
// initActionBars();
modelListener = new PaletteModelListener();
model.addModelTreeListener(modelListener);
return pane;
}
private void createPaletteTabs() {
IActionBars bars = viewPart.getActionBars();
if(bars == null) return;
IMenuManager menuManager = bars.getMenuManager();
IPaletteNode root = model.getRoot();
IPaletteNode[] nodes = root.getChildren();
if (nodes != null) {
for (int i = 0; i < nodes.length; i++) {
createPaletteTab(nodes[i], menuManager);
}
}
}
private void createPaletteTab(IPaletteNode node, IMenuManager manager) {
String title = node.getTitle();
Composite tab = new Composite(pane, SWT.NONE);
tab.setData(node);
RowLayout layout = new RowLayout(SWT.HORIZONTAL);
layout.pack = true;
layout.justify = false;
layout.marginLeft = 0;
layout.marginTop = 0;
layout.marginRight = 0;
layout.marginBottom = 0;
layout.spacing = 0;
tab.setLayout(layout);
IPaletteNode[] elems = node.getChildren();
if (elems != null) {
for (int i = 0; i < elems.length; i++) {
createPaletteElement(tab, elems[i]);
}
}
manager.add(new PaletteTabAction(tab, title));
}
private void createPaletteElement(Composite tab, IPaletteNode node) {
ToolBar tlb = new ToolBar(tab, SWT.HORIZONTAL | SWT.FLAT);
ToolItem item = new ToolItem(tlb, SWT.PUSH);
item.setText(StringUtilities.dottedString(node.getTitle(), IconUtil.PALETTE_IMAGE_WIDTH - TEXT_MARGIN, tlb));
Image image = node.getImage();
if (image != null) {
image.setBackground(tlb.getBackground());
image.setBackground(new org.eclipse.swt.graphics.Color(tlb.getDisplay(), 255, 0, 0));
item.setImage(image);
if (fWindowsFlag)
item.setDisabledImage(image);
}
item.setData(node);
item.addSelectionListener(new PaletteSelectionListener(node));
}
public void setEnabled(boolean enabled) {
if (!fWindowsFlag) return;
Control[] tabs = pane.getChildren();
for (int i = 0; i < tabs.length; i++) {
if (tabs[i] instanceof Composite) {
Control[] elems = ((Composite)tabs[i]).getChildren();
for (int j = 0; j < elems.length; j++) {
if (elems[j] instanceof ToolBar) {
ToolBar tlb = (ToolBar)elems[j];
for (int k = 0, c = tlb.getItemCount(); k < c; k++) {
tlb.getItem(k).setEnabled(enabled);
}
}
}
}
}
}
private void reload(XModelObject xtab) {
model.reload();
IActionBars bars = viewPart.getActionBars();
IMenuManager menuManager = bars.getMenuManager();
String oldTitle = null;
Control oldTab = pane.getContent();
Control[] oldTabs = pane.getChildren();
IContributionItem[] oldActions = menuManager.getItems();
createPaletteTabs();
for (int i = 0; i < oldActions.length; i++) {
if (oldTitle == null && oldTab != null && oldActions[i] instanceof ActionContributionItem) {
IAction action = ((ActionContributionItem)oldActions[i]).getAction();
if ((action instanceof PaletteTabAction) && ((PaletteTabAction)action).tab == oldTab) {
oldTitle = action.getText();
}
}
menuManager.remove(oldActions[i]);
}
IAction newAction = null;
IContributionItem[] newActions = menuManager.getItems();
if (xtab != null) {
for (int i = 0; i < newActions.length; i++) {
if (newActions[i] instanceof ActionContributionItem) {
IAction action = ((ActionContributionItem)newActions[i]).getAction();
if ((action instanceof PaletteTabAction) && ((IPaletteNode)((Composite)((PaletteTabAction)action).tab).getData()).getXModelObject() == xtab) {
newAction = action;
break;
}
}
}
}
if (newAction == null && oldTitle != null) {
for (int i = 0; i < newActions.length; i++) {
if (newActions[i] instanceof ActionContributionItem) {
IAction action = ((ActionContributionItem)newActions[i]).getAction();
if (oldTitle.equalsIgnoreCase(action.getText())) {
newAction = action;
break;
}
}
}
}
if (newAction == null) {
if (newActions.length > 0 && (newActions[0] instanceof ActionContributionItem)) {
newAction = ((ActionContributionItem)newActions[0]).getAction();
}
}
if (newAction != null) {
newAction.run();
}
for (int i = 0; i < oldTabs.length; i++) {
oldTabs[i].dispose();
}
setEnabled(viewPart.isEnabled());
}
public void dispose() {
dropManager.dispose();
descriptionManager.dispose();
if(model != null) model.removeModelTreeListener(modelListener);
if(viewPart.getActionBars() != null) viewPart.getActionBars().getToolBarManager().removeAll();
try {
if (selectedTab != null) {
ModelUIPlugin.getWorkspace().getRoot().setPersistentProperty(persistentTabQualifiedName, selectedTab);
}
} catch (CoreException e) {
ModelUIPlugin.getPluginLog().logError(e);
}
}
public void setPaletteContents(PaletteContents contents) {
}
private class PaletteTabAction extends Action {
private Composite tab;
public PaletteTabAction(Composite tab, String text) {
super(text);
this.tab = tab;
setId(text);
}
public Composite getTab() {
return tab;
}
public void run() {
if (pane.getContent() != null) {
dropManager.dispose();
resizeManager.dispose();
descriptionManager.setEnabled(false);
}
viewPart.setContentDescription(getText());
pane.setContent(tab);
descriptionManager.install(tab);
resizeManager.install(tab);
dropManager.install(tab);
selectedTab = getId();
}
}
private class PaletteResizeManager extends ControlAdapter {
Composite tab = null;
public void install(Composite tab) {
dispose();
this.tab = tab;
resize();
tab.addControlListener(this);
}
public void dispose() {
if (tab != null) {
if (!tab.isDisposed()) {
tab.removeControlListener(this);
}
tab = null;
}
}
public void controlResized(ControlEvent event) {
resize();
}
private void resize() {
int width = pane.getClientArea().width;
if (width > 0) {
int height = tab.computeSize(width, SWT.DEFAULT).y;
pane.setMinHeight(height);
}
}
}
private class PaletteSelectionListener extends SelectionAdapter {
IPaletteNode node;
public PaletteSelectionListener(IPaletteNode node) {
super();
this.node = node;
}
public void widgetSelected(SelectionEvent event) {
viewPart.insertIntoEditor(((PaletteElement)node).getXModelObject());
}
}
private class PaletteDropTargetManager extends DropTargetAdapter {
private DropTarget target = null;
public void install(Composite tab) {
dispose();
Transfer[] types = new Transfer[]{
ModelTransfer.getInstance(),
FileTransfer.getInstance()
};
target = new DropTarget(tab, DND.DROP_MOVE | DND.DROP_COPY);
target.setTransfer(types);
target.addDropListener(this);
}
public void dispose() {
if (target != null) {
if(!target.isDisposed()) {
target.removeDropListener(this);
target.dispose();
}
target = null;
}
}
public void dragOver(DropTargetEvent event) {
XModelObject o = null;
if(FileTransfer.getInstance().isSupportedType(event.currentDataType)) {
File f = getFile(event);
if(f != null) {
IFile ef = EclipseResourceUtil.getFile(f.getAbsolutePath());
o = (ef == null) ? null : EclipseResourceUtil.getObjectByResource(ef);
}
} else if (event.currentDataType.type != ModelTransfer.MODEL_ID) {
o = null;
} else {
o = getModelObject(event.x, event.y);
}
boolean enabled = o != null && DnDUtil.isPasteEnabled(o);
event.detail = enabled ? DND.DROP_COPY : DND.DROP_NONE;
}
public void drop(DropTargetEvent event) {
XModelObject o = null;
if(FileTransfer.getInstance().isSupportedType(event.currentDataType)) {
File f = getFile(event);
if(f != null) {
IFile ef = EclipseResourceUtil.getFile(f.getAbsolutePath());
o = (ef == null) ? null : EclipseResourceUtil.getObjectByResource(ef);
}
} else if(event.currentDataType.type != ModelTransfer.MODEL_ID) {
o = null;
} else {
o = getModelObject(event.x, event.y);
}
if(o != null) {
try {
DnDUtil.paste(o, new Properties());
model.getXModel().saveOptions();
} catch (ActionDeclinedException ade) {
//ignore - this exception is thrown to inform that user
//selected cancel option in dialog.
} catch (XModelException e) {
message(e);
}
} else {
event.detail = DND.DROP_NONE;
}
}
private XModelObject getModelObject(int x, int y) {
IPaletteNode node = null;
Composite tab = (Composite)target.getControl();
Control[] controls = tab.getChildren();
for (int i = 0; i < controls.length; i++) {
if (controls[i] instanceof ToolBar) {
Rectangle area = controls[i].getBounds();
if (area.contains(x, y)) {
ToolItem item = ((ToolBar)controls[i]).getItem(new Point(x - area.x, y - area.y));
if (item != null) {
node = (IPaletteNode)item.getData();
}
break;
}
}
}
if (node == null) {
node = (IPaletteNode)tab.getData();
}
return node.getXModelObject();
}
private void message(Exception e) {
ModelUIPlugin.getPluginLog().logError( e);
}
private File getFile(DropTargetEvent event) {
String[] s = (String[])event.data;
return(s == null || s.length == 0) ? null : new File(s[0]);
}
}
private class PaletteModelListener implements XModelTreeListener {
private boolean isTransaction = false;
private boolean isDirty = false;
private XModelObject lastAddedTab = null;
public void nodeChanged(XModelTreeEvent event) {
run(event);
}
public void structureChanged(XModelTreeEvent event) {
run(event);
}
private void run(XModelTreeEvent event) {
if("transaction_begin".equals(event.getInfo())) { //$NON-NLS-1$
isTransaction = true;
return;
}
if("transaction_end".equals(event.getInfo())) { //$NON-NLS-1$
isTransaction = false;
if(isDirty) {
isDirty = false;
reload(lastAddedTab);
lastAddedTab = null;
}
return;
}
XModel xmodel = model.getXModel();
XModelObject exo = event.getModelObject();
boolean q = event.kind() == XModelTreeEvent.STRUCTURE_CHANGED && xmodel.getRoot().getPath().equals(exo.getPath());
XModelObject xroot = xmodel.getRoot("Palette"); //$NON-NLS-1$
if (xroot == null || isExist(xroot, event.getModelObject()) || q) {
if (event.kind() == XModelTreeEvent.CHILD_ADDED && xroot != null && xroot.getPath().equals(exo.getPath())) {
Object info = event.getInfo();
if (info instanceof XModelObject) {
lastAddedTab = (XModelObject)info;
}
}
if(isTransaction) {
isDirty = true;
} else {
reload(lastAddedTab);
lastAddedTab = null;
}
}
}
private boolean isExist(XModelObject root, XModelObject modelObject) {
if (root == null || modelObject==null) {
return false;
}
if (modelObject.getPath() == null || root.getPath() == null) {
return false;
}
return (modelObject.getPath() + "/").startsWith(root.getPath() + "/"); //$NON-NLS-1$ //$NON-NLS-2$
}
}
private class PaletteEditAction extends Action {
public PaletteEditAction() {
super("Palette Editor", model.createImageDescriptor("palette_editor.gif")); //$NON-NLS-2$
setToolTipText("Palette Editor");
}
public void run() {
model.openEditor(pane.getShell());
}
}
private class ShowHideTabsAction extends Action {
public ShowHideTabsAction() {
super("Show/Hide tabs", model.createImageDescriptor("show-hide.gif")); //$NON-NLS-2$
setToolTipText("Show/Hide");
}
public void run() {
model.runShowHideDialog();
}
}
}