/******************************************************************************* * Copyright (c) 2014 Elphel, Inc. * Copyright (c) 2006 Elphel, Inc and Excelsior, LLC. * This file is a part of VDT plug-in. * VDT plug-in is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * VDT plug-in is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see <http://www.gnu.org/licenses/>. * * Additional permission under GNU GPL version 3 section 7: * If you modify this Program, or any covered work, by linking or combining it * with Eclipse or Eclipse plugins (or a modified version of those libraries), * containing parts covered by the terms of EPL/CPL, the licensors of this * Program grant you additional permission to convey the resulting work. * {Corresponding Source for a non-source form of such a combination shall * include the source code for the parts of Eclipse or Eclipse plugins used * as well as that of the covered work.} *******************************************************************************/ package com.elphel.vdt.ui.views; //import org.eclipse.swt.SWT; import org.eclipse.swt.graphics.Rectangle; import java.io.File; import java.util.List; import java.util.ArrayList; import java.util.Iterator; import java.util.Timer; import java.util.TimerTask; import java.util.concurrent.atomic.AtomicBoolean; import org.eclipse.core.resources.IResource; //import org.eclipse.jface.viewers.TreeViewer; //import org.eclipse.swt.graphics.GC; import org.eclipse.swt.graphics.Image; import org.eclipse.swt.graphics.ImageData; import org.eclipse.swt.widgets.Display; import org.eclipse.swt.widgets.Event; //import org.eclipse.swt.widgets.Listener; import org.eclipse.swt.widgets.Tree; import org.eclipse.swt.widgets.TreeItem; import com.elphel.vdt.VDT; import com.elphel.vdt.core.tools.ToolsCore; import com.elphel.vdt.core.tools.config.Config; import com.elphel.vdt.core.tools.contexts.PackageContext; import com.elphel.vdt.core.tools.contexts.ProjectContext; import com.elphel.vdt.core.tools.menu.DesignMenu; import com.elphel.vdt.core.tools.menu.DesignMenuItem; import com.elphel.vdt.core.tools.menu.DesignMenuToolItem; import com.elphel.vdt.core.tools.params.Tool; import com.elphel.vdt.core.tools.params.Tool.TOOL_STATE; import com.elphel.vdt.ui.VDTPluginImages; import com.elphel.vdt.ui.variables.SelectedResourceManager; /** * Adapter of core design menu for user interface level. * * Created: 28.03.2006 * @author Lvov Konstantin */ public class DesignMenuModel { private Config config; private MenuItem root; private final int IMAGE_MARGIN=2; public DesignMenuModel(DesignMenu menu) { config = ToolsCore.getConfig(); root = new MenuItem(null, menu); } public Item[] getItems() { return root.getChildren(); } // ------------------------------------------------------------------------ public abstract class Item { private static final String ICON_ID_PREFIX = VDT.ID_VDT + ".DesignMenu.Image."; private String imageKey = null; protected String imageKeyState = null; private DesignMenuItem source; private Item parent; private int animN; private Rectangle animBounds=null; private ImageData[] imageData=null; // private boolean animEn=true; // just testing, fill be false; final private AtomicBoolean animBusy=new AtomicBoolean(false); private Timer timer=null; // private int updateWidth=16; private Item(Item parent, DesignMenuItem source) { this.parent = parent; this.source = source; this.timer=null; String image = source.getIcon(); if (image != null) { // imageKey = ICON_ID_PREFIX + source.getName(); imageKey = ICON_ID_PREFIX + (new File(source.getName())).getName(); if (VDTPluginImages.getImage(imageKey) == null) VDTPluginImages.addImage(image, imageKey, null/*tool.getLaunchType()*/); } } public boolean isEnabled(IResource resource) { return false; } public boolean isEnabled(String path) { return false; } public Object getParent() { return parent; } public Item[] getChildren() { return new Item[0]; } public boolean hasChildren() { return false; } public String toString() { String label = source.getLabel(); return label != null ? label : "Unknown"; } public String getLabel() { return toString(); } public String getImageKey() { return imageKey; } public void measureItem (Event event){ if (imageKeyState==null) return; Image image=VDTPluginImages.getImage(imageKeyState); if (image!=null) event.width+=IMAGE_MARGIN+image.getBounds().width; } public void showStateIcon(Event event, final Tree tree, final TreeItem item){ if ((imageKeyState==null) || (item.isDisposed())) return; int x = event.x + event.width + IMAGE_MARGIN; int itemHeight = tree.getItemHeight(); imageData=VDTPluginImages.getImageData(imageKeyState); Image frameImage; boolean isAnimation=false; if ((imageData!=null) && (imageData.length>1) && animBusy.compareAndSet(false,true)){ isAnimation=true; animN=animN % imageData.length; frameImage = new Image(Display.getDefault(),imageData[animN]); } else { frameImage = VDTPluginImages.getImage(imageKeyState); // do not dispose() ! } int imageHeight = frameImage.getBounds().height; int y = event.y + (itemHeight - imageHeight) / 2; event.gc.drawImage(frameImage, x, y); // System.out.println("showStateIcon(): "+imageKeyState); if (isAnimation){ animBounds=frameImage.getBounds(); frameImage.dispose(); final int fDelayTime=imageData[animN].delayTime*10; // ms animN++; // item does not include our animation on the right of it, so we need to store image location // relative to the top right corner of the item (height does not change) Rectangle r=item.getBounds(); animBounds.x=x-(r.x+r.width); animBounds.y=y-(r.y); TimerTask timerTask=new TimerTask() { @Override public void run() { refresh(item, tree); // threw on shutdown - } }; if (timer==null) timer=new Timer(); try { timer.schedule(timerTask, fDelayTime); } catch (IllegalStateException e){ System.out.println("DesignMenuModel(): Timer was somewhere canceled, recovering"); timer.cancel(); timer=new Timer(); timer.schedule(timerTask, fDelayTime); } /* timer.schedule(new TimerTask() { @Override public void run() { refresh(item, tree); // threw on shutdown - } }, fDelayTime); */ } } public void refresh(final TreeItem item, final Tree tree) { Display.getDefault().syncExec(new Runnable() { public void run() { if (item.isDisposed()) { animBusy.compareAndSet(true, false); return; } Rectangle r=item.getBounds(); // System.out.println("animBounds="+animBounds.toString()+" item.getBounds()="+item.getBounds().toString()); tree.redraw( animBounds.x+r.x+r.width, animBounds.y+r.y, animBounds.width, animBounds.height,true); animBusy.compareAndSet(true, false); } }); } public Tool getTool() { return null; } public Config getConfig() { return null; } public PackageContext getPackageContext() { return null; } public ProjectContext getProjectContext() { return null; } } // class Item // ------------------------------------------------------------------------ public class ToolItem extends Item { private Tool tool; private ToolItem(Item parent, DesignMenuToolItem source) { super(parent, source); tool = ToolsCore.getTool(source.getToolName()); } public boolean isEnabled(IResource resource) { if (resource == null) return false; String extensions[] = tool.getExtensions(); if (extensions == null) return true; String resourceExt = resource.getFileExtension(); if (resourceExt == null) return false; for (int i=0; i < extensions.length; i++) { if (resourceExt.equalsIgnoreCase(extensions[i])) return true; } return false; } // isEnabled(IResource) public boolean isEnabled(String path) { if (path == null) return false; String extensions[] = tool.getExtensions(); if (extensions == null) return true; int index=path.indexOf("."); if (index<0) return false; String resourceExt = path.substring(index+1); for (int i=0; i < extensions.length; i++) { if (resourceExt.equalsIgnoreCase(extensions[i])) return true; } return false; } // isEnabled(String) public Tool getTool() { return tool; } public Config getConfig() { return config; } public PackageContext getPackageContext() { PackageContext context = tool.getParentPackage(); if ((context != null) && context.isVisible()) return context; else return null; } public ProjectContext getProjectContext() { ProjectContext context = tool.getParentProject(); if ((context != null) && context.isVisible()) return context; else return null; } public void measureItem (Event event){ super.measureItem (event); boolean pinned=tool.isPinned() || !SelectedResourceManager.getDefault().isToolsLinked(); String iconName,key; if (tool.isRunning()){ iconName=VDTPluginImages.ICON_TOOLSTATE_RUNNING; key= VDTPluginImages.KEY_TOOLSTATE_RUNNING; } else if (tool.isWaiting()){ iconName=VDTPluginImages.ICON_TOOLSTATE_WAITING; key= VDTPluginImages.KEY_TOOLSTATE_WAITING; } else if (tool.isAlmostDone()&& (tool.getState()==TOOL_STATE.SUCCESS )){ iconName=VDTPluginImages.ICON_TOOLSTATE_ALMOST_GOOD; key= VDTPluginImages.KEY_TOOLSTATE_ALMOST_GOOD; } else if (tool.isAlmostDone()&& (tool.getState()==TOOL_STATE.UNKNOWN )){ iconName=VDTPluginImages.ICON_TOOLSTATE_ALMOST_WTF; key= VDTPluginImages.KEY_TOOLSTATE_ALMOST_WTF; } else if (tool.isAlmostDone()){ // restoring state, current state new (erased) or failure iconName=VDTPluginImages.ICON_TOOLSTATE_ALMOST_GOOD; key= VDTPluginImages.KEY_TOOLSTATE_ALMOST_GOOD; } else { switch (tool.getState()){ case NEW: iconName=VDTPluginImages.ICON_TOOLSTATE_NEW; key= VDTPluginImages.KEY_TOOLSTATE_NEW; break; case FAILURE: if (tool.isDirtyOrChanged()){ iconName=VDTPluginImages.ICON_TOOLSTATE_BAD_OLD; key= VDTPluginImages.KEY_TOOLSTATE_BAD_OLD; } else { iconName=VDTPluginImages.ICON_TOOLSTATE_BAD; key= VDTPluginImages.KEY_TOOLSTATE_BAD; } break; case SUCCESS: if (pinned){ iconName=VDTPluginImages.ICON_TOOLSTATE_PINNED; key= VDTPluginImages.KEY_TOOLSTATE_PINNED; } else { if (tool.isDirtyOrChanged()){ iconName=VDTPluginImages.ICON_TOOLSTATE_GOOD_OLD; key= VDTPluginImages.KEY_TOOLSTATE_GOOD_OLD; } else { iconName=VDTPluginImages.ICON_TOOLSTATE_GOOD; key= VDTPluginImages.KEY_TOOLSTATE_GOOD; } } break; case KEPT_OPEN: iconName=VDTPluginImages.ICON_TOOLSTATE_KEPT_OPEN; key= VDTPluginImages.KEY_TOOLSTATE_KEPT_OPEN; break; default: if (tool.isDirtyOrChanged()){ iconName=VDTPluginImages.ICON_TOOLSTATE_WTF_OLD; key= VDTPluginImages.KEY_TOOLSTATE_WTF_OLD; } else { iconName=VDTPluginImages.ICON_TOOLSTATE_WTF; key= VDTPluginImages.KEY_TOOLSTATE_WTF; } } } key = Item.ICON_ID_PREFIX + key; if (VDTPluginImages.getImage(key) == null){ VDTPluginImages.addImage(iconName, key, null); } super.imageKeyState=key; // System.out.println("iconName="+iconName+", key="+key+" imageKeyState="+super.imageKeyState); /* */ //TODO: Save tool state in memento } } // class ToolItem // ------------------------------------------------------------------------ public class MenuItem extends Item { private Item[] items; private MenuItem(Item parent, DesignMenu source) { super(parent, source); List<Item> itemList = new ArrayList<Item>(); for(Iterator<DesignMenuItem> i = source.getItems().iterator(); i.hasNext();) { DesignMenuItem menuitem = (DesignMenuItem)i.next(); if(menuitem.isVisible()) itemList.add(CreateItem(this, menuitem)); } items = (Item[])itemList.toArray(new Item[itemList.size()]); } public Item[] getChildren() { return items; } public boolean hasChildren() { return items.length > 0; } } // class MenuItem private Item CreateItem(Item parent, DesignMenuItem source) { if (source instanceof DesignMenuToolItem) return new ToolItem(parent, (DesignMenuToolItem)source); else if (source instanceof DesignMenu) return new MenuItem(parent, (DesignMenu)source); else assert(false); return null; } } // class DesignMenuModel