/*
* Scriptographer
*
* This file is part of Scriptographer, a Scripting Plugin for Adobe Illustrator
* http://scriptographer.org/
*
* Copyright (c) 2002-2010, Juerg Lehni
* http://scratchdisk.com/
*
* All rights reserved. See LICENSE file for details.
*
* File created on 19.02.2005.
*/
package com.scriptographer.ui;
import java.util.ArrayList;
import com.scriptographer.ScriptographerEngine;
import com.scriptographer.ScriptographerException;
import com.scratchdisk.script.Callable;
import com.scratchdisk.util.IntMap;
/*
* Theoretically MenuItem and MenuGroup would belong to the AI package, not UI
* But as these are the only classes dealing with the interface there, they were
* moved here instead, where they make more sense.
*/
/**
* @author lehni
*/
public class MenuItem extends NativeObject{
public static final int
OPTION_NONE = 0,
OPTION_WANTS_UPDATE = 1 << 0,
OPTION_ALWAYS_ENABLED = 1 << 1,
OPTION_SEPARATOR = 1 << 2;
public static final int
MODIFIER_NONE = 0,
MODIFIER_SHIFT = 1 << 0,
MODIFIER_OPTION = 1 << 1,
MODIFIER_COMMAND = 1 << 2;
protected String name;
protected MenuGroup group;
private MenuGroup subGroup;
private static IntMap<MenuItem> items = null;
private static int uniqueId = 0;
public MenuItem(MenuGroup group, int options) {
name = "Scriptographer MenuItem " + (++uniqueId);
this.group = group;
IntMap<MenuItem> items = getItems();
Integer handle = items.keyOf(this);
if (handle != null) {
// Take over the handle from the other item
items.get(handle).handle = 0;
this.handle = handle;
}
// if no item has been taken over, create a new one:
if (this.handle == 0)
this.handle = nativeCreate(name, name, group.name, options);
if (this.handle == 0)
throw new ScriptographerException("Unable to create MenuItem.");
items.put(this.handle, this);
}
public MenuItem(MenuGroup group) {
this(group, OPTION_NONE);
}
/**
* Creates the MenuItem as a subitem of parentItem. If parentItem does not
* have a sub group already, one with default parameters is created. If a
* group with other options is needed, use createSubGroup and pass the
* resulting group to the constructor that takes a group as third parameter.
*
* @see #MenuItem(MenuGroup, int)
*/
public MenuItem(MenuItem parentItem, int options) {
// If a subGroup as created earlier, createSubGroup does not create a
// new one
this(parentItem.createSubGroup(), options);
}
public MenuItem(MenuItem parentItem) {
this(parentItem, OPTION_NONE);
}
public MenuGroup getSubGroup() {
return subGroup;
}
/**
*
* @param options MenuGroup.OPTION_*
*/
public MenuGroup createSubGroup(int options) {
if (subGroup == null)
subGroup = new MenuGroup(this, options);
return subGroup;
}
public MenuGroup createSubGroup() {
return createSubGroup(MenuGroup.OPTION_NONE);
}
/**
* Used in wrapHandle
*
* @param handle
* @param name
* @param text
*/
protected MenuItem(int handle, String name, MenuGroup group) {
super(handle);
this.name = name;
this.group = group;
items.put(this.handle, this);
}
/**
* Called from the native environment to wrap a MenuItem:
*
* @param handle
* @param name
* @param text
* @param groupHandle
* @param groupName
*/
protected static MenuItem wrapHandle(int handle, String name,
int groupHandle, String groupName) {
MenuItem item = getItem(handle);
if (item == null)
item = new MenuItem(handle, name, MenuGroup.wrapHandle(
groupHandle, groupName));
return item;
}
public void remove() {
if (subGroup == null)
nativeRemove(handle);
if (items.get(handle) == this)
items.remove(handle);
handle = 0;
}
public static void removeAll() {
// As remove() modifies the map, using an iterator is not possible here:
Object[] items = MenuItem.items.values().toArray();
for (int i = 0; i < items.length; i++) {
((MenuItem) items[i]).remove();
}
}
private static native int nativeCreate(String name, String text,
String group, int options);
private static native int nativeRemove(int handle);
public boolean equals(Object obj) {
if (obj instanceof MenuItem) {
MenuItem item = (MenuItem) obj;
return name.equals(item.name) &&
group.equals(item.group);
}
return false;
}
public native String getText();
public native void setText(String text);
public native void setOptions(int options);
public native int getOptions();
public native void setEnabled(boolean enabled);
public native boolean isEnabled();
public native void setChecked(boolean checked);
public native boolean isChecked();
public void setSeparator(boolean separator) {
int options = getOptions();
if (separator) options |= OPTION_SEPARATOR;
else options &= ~OPTION_SEPARATOR;
setOptions(options);
// This seems to do the trick really:
setText(separator ? "-" : "");
}
public boolean getSeparator() {
return (getOptions() & OPTION_SEPARATOR) != 0;
}
// TODO: add support for UpdateMenuItemAutomatically and all the parameters
// needed for it
// Callback functions:
private Callable onSelect = null;
public Callable getOnSelect() {
return onSelect;
}
public void setOnSelect(Callable onSelect) {
this.onSelect = onSelect;
}
protected void onSelect() {
if (onSelect != null)
ScriptographerEngine.invoke(onSelect, this);
}
private Callable onUpdate = null;
public Callable getOnUpdate() {
return onUpdate;
}
public void setOnUpdate(Callable onUpdate) {
this.onUpdate = onUpdate;
int options = this.getOptions();
if (onUpdate != null) options |= OPTION_WANTS_UPDATE;
else options &= ~OPTION_WANTS_UPDATE;
this.setOptions(options);
}
protected void onUpdate(int inArtwork, int isSelected, int isTrue) {
if (onUpdate != null)
ScriptographerEngine.invoke(onUpdate, this);
}
/**
* To be called from the native environment:
*/
private static void onSelect(int handle) {
MenuItem item = getItem(handle);
if (item != null)
item.onSelect();
}
/**
* To be called from the native environment:
*/
private static void onUpdate(int handle, int inArtwork, int isSelected,
int isTrue) {
MenuItem item = getItem(handle);
if (item != null)
item.onUpdate(inArtwork, isSelected, isTrue);
}
private static MenuItem getItem(int handle) {
return getItems().get(handle);
}
private static IntMap<MenuItem> getItems() {
if (items == null) {
items = new IntMap<MenuItem>();
for (MenuItem item : nativeGetItems())
items.put(item.handle, item);
}
return items;
}
private static native ArrayList<MenuItem> nativeGetItems();
public native boolean setCommand(String key, int modifiers);
}