/* * 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 31.12.2004. */ package com.scriptographer.adm; import java.io.IOException; import java.util.Iterator; import com.scratchdisk.list.ExtendedList; import com.scratchdisk.list.List; import com.scratchdisk.list.ListIterator; import com.scratchdisk.list.Lists; import com.scratchdisk.list.ReadOnlyList; import com.scratchdisk.list.ReadOnlyStringIndexList; import com.scratchdisk.script.Callable; import com.scriptographer.ScriptographerEngine; /** * ListItem is a UI list item (e.g. ListBox, PopupMenu, ...) and a * UI list object (e.g. ListBox, HierarchyListBox) in one. It melts the * two objects to one and makes handling much easier. * * @author lehni */ /* The GetList() function returns a reference to inItem's ADM List object. Once obtained, the ADM List suite functions can be used to access the list. The following item types have valid list objects: #define kADMListBoxType "ADM List Box Type" #define kADMPopupListType "ADM Popup List Type" #define kADMPopupMenuType "ADM Popup Menu Type" #define kADMScrollingPopupListType "ADM Scrolling Popup List Type" #define kADMSpinEditPopupType "ADM Spin Edit Popup Type" #define kADMSpinEditScrollingPopupType "ADM Spin Edit Scrolling Popup Type" #define kADMTextEditPopupType "ADM Text Edit Popup Type" #define kADMTextEditScrollingPopupType "ADM Text Edit Scrolling Popup Type" */ public abstract class ListItem<E extends ListEntry> extends Item implements List<E>, ReadOnlyStringIndexList<E> { protected ListItem(Dialog dialog, ItemType type) { super(dialog, type); listHandle = nativeInit(handle); } protected ListItem(Dialog dialog, int handle, boolean isChild) { super(dialog, handle, isChild); listHandle = nativeInit(handle); } /** * Empty constructor used for nested HierarchyListBoxes */ protected ListItem() { } private Callable onPreChange = null; public Callable getOnPreChange() { return onPreChange; } public void setOnPreChange(Callable onPreChange) { this.onPreChange = onPreChange; } protected void onPreChange() { if (onPreChange != null) ScriptographerEngine.invoke(onPreChange, this); } private Callable onChange = null; protected void onChange() { if (onChange != null) ScriptographerEngine.invoke(onChange, this); } public Callable getOnChange() { return onChange; } public void setOnChange(Callable onChange) { this.onChange = onChange; } protected void onNotify(Notifier notifier) { super.onNotify(notifier); switch(notifier) { case USER_CHANGED: onChange(); break; case INTERMEDIATE_CHANGED: onPreChange(); break; } } protected int listHandle = 0; private int uniqueId = 0; private DialogColor bgColor = DialogColor.BACKGROUND; protected int getUniqueId() { return uniqueId++; } private native int nativeInit(int itemHandle); /* * Callback functions */ public native void setTrackEntryMask(int mask); public native int getTrackEntryMask(); private boolean trackEntryCallback = false; private boolean drawEntryCallback = false; public void setTrackEntryCallback(boolean enabled) { nativeSetTrackEntryCallback(enabled); trackEntryCallback = enabled; } public boolean getTrackEntryCallback() { return trackEntryCallback; } public void setDrawEntryCallback(boolean enabled) { nativeSetDrawEntryCallback(enabled); drawEntryCallback = enabled; } public boolean getDrawEntryCallback() { return drawEntryCallback; } private Callable onTrackEntry = null; public Callable getOnTrackEntry() { return onTrackEntry; } public void setOnTrackEntry(Callable func) { setTrackEntryCallback(func != null); onTrackEntry = func; } private Callable onDrawEntry = null; public Callable getOnDrawEntry() { return onDrawEntry; } public void setOnDrawEntry(Callable func) { setDrawEntryCallback(func != null); onDrawEntry = func; } private Callable onDestroyEntry = null; public Callable getOnDestroyEntry() { return onDestroyEntry; } public void setOnDestroyEntry(Callable func) { onDestroyEntry = func; } private Callable onSelectEntry = null; public Callable getOnSelectEntry() { return onSelectEntry; } public void setOnSelectEntry(Callable func) { onSelectEntry = func; } private Callable onChangeEntryText = null; public Callable getOnChangeEntryText() { return onChangeEntryText; } public void setOnChangeEntryText(Callable onChangeEntryText) { this.onChangeEntryText = onChangeEntryText; } protected void onNotify(Notifier notifier, E entry) { // redirect to the entry that takes care of this: entry.onNotify(notifier); } /* * Handler activation / deactivation */ protected native void nativeSetTrackEntryCallback(boolean enabled); protected native void nativeSetDrawEntryCallback(boolean enabled); /* * menu IDs * */ /* public native void setMenuID(SPPluginRef inMenuResPlugin, ADMInt32 inMenuResID, const char* inMenuResName); public native ADMInt32 getMenuID(ADMListRef inList); */ /* * container accessor * */ // public native Item getItem(); /* * override hooks * */ /* * entry bounds accessors * */ /** * @jshide */ public native void setEntrySize(int width, int height); public native Size getEntrySize(); public void setEntrySize(Size size) { setEntrySize(size.width, size.height); } /** * @jshide */ public native void setEntryTextRect(int x, int y, int width, int height); public native Rectangle getEntryTextRect(); public void setEntryTextRect(Rectangle rect) { Size entrySize = getEntrySize(); if (rect.width > entrySize.width || rect.height > entrySize.height) setEntrySize( Math.max(rect.width, entrySize.width), Math.max(rect.height, entrySize.height)); setEntryTextRect(rect.x, rect.y, rect.width, rect.height); } /* * customizing appearance * */ private native void nativeSetBackgroundColor(int color); public void setBackgroundColor(DialogColor color) { if (color != null) { bgColor = color; nativeSetBackgroundColor(color.value); } } public DialogColor getBackgroundColor() { return bgColor; } /* * searching * */ public native void selectByText(String text); /* * entry array accessors * */ public native E get(String text); /** * @jshide */ public native E getAt(int x, int y); public E getAt(Point point) { return getAt(point.x, point.y); } public native E getSelectedEntry(); public void setSelectedEntry(E entry) { for (E prev : getSelectedEntries()) prev.setSelected(false); if (entry != null && entry.getList() == this) entry.setSelected(true); } /** * @deprecated */ public E getActiveEntry() { return getSelectedEntry(); } public native E[] getSelectedEntries(); /** * @deprecated */ public E[] getSelected() { return getSelectedEntries(); } /* * List interface * */ public native int size(); public native E get(int index); public E set(int index, E element) { E old = remove(index); if (old != null && add(index, element) != null) { return old; } return null; } protected abstract E createEntry(int index); public E add(int index, E entry) { E res = createEntry(index); res.setText(entry.getText()); res.setEnabled(entry.isEnabled()); res.setActive(entry.isActive()); res.setChecked(res.isChecked()); res.setSeparator(entry.isSeparator()); try { res.setImage(entry.getImage()); res.setSelectedImage(entry.getSelectedImage()); res.setDisabledImage(entry.getDisabledImage()); } catch (IOException e) { // will never happen with images } return res; } public E add(int index, String element) { E entry = createEntry(index); entry.setText(element); return entry; } // TODO: think about some kind of field value cashing in E // otherwise values returned by remove() are unusable and cannot // be added to the list again. public native E remove(int index); // as there is no Polymorphism in Java, so all these need to be copied // over from AbstractList. public E add(E element) { return add(-1, element); } public E add(String element) { return add(-1, element); } public void remove(int fromIndex, int toIndex) { for (int i = toIndex - 1; i >= fromIndex; i--) remove(i); } public final void removeAll() { remove(0, size()); } /** * @jshide */ public boolean addAll(ReadOnlyList<? extends E> elements) { boolean modified = false; int size = elements.size(); int index = size(); for (int i = 0; i < size; i++) { if (add(index++, elements.get(i)) != null) modified = true; } return modified; } public final boolean addAll(E[] elements) { return addAll(Lists.asList(elements)); } /** * @jshide */ public ExtendedList<E> getSubList(int fromIndex, int toIndex) { return Lists.createSubList(this, fromIndex, toIndex); } /** * @jshide */ public boolean isEmpty() { return size() == 0; } public Iterator<E> iterator() { return new ListIterator<E>(this); } public E getFirst() { return size() > 0 ? get(0) : null; } public E getLast() { int size = size(); return size > 0 ? get(size - 1) : null; } public Class<? extends ListEntry> getComponentType() { return ListEntry.class; } }