/* * 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 Feb 23, 2010. */ package com.scriptographer.ui; import java.util.LinkedHashMap; import java.util.Map; import com.scratchdisk.script.Callable; import com.scratchdisk.script.PropertyObserver; import com.scratchdisk.script.ScriptEngine; import com.scriptographer.CommitManager; import com.scriptographer.Committable; import com.scriptographer.ScriptographerEngine; /** * @author lehni * */ public class Palette implements PropertyObserver, Committable { private String title; private Map<String, Object> values; private Map<String, Object> components; private boolean sizeChanged; private boolean hasLabels; private PaletteProxy proxy; public Palette(String title, Map<String, Object> components, Map<String, Object> values) { if (values != null) { // Observer all existing properties for changes for (Object key : values.keySet()) ScriptEngine.observeChanges(values, key, this); } else { values = new LinkedHashMap<String, Object>(); } if (components == null) components = new LinkedHashMap<String, Object>(); this.title = title; this.values = values; this.components = components; Component[] comps = Component.getComponents(components, values); hasLabels = false; // Store references to palette in each component, and determine if there // are labels for (Component component : comps) { if (component != null) { component.palette = this; String label = component.getLabel(); if (label != null && !"".equals(label)) hasLabels = true; } } proxy = UiFactory.getInstance().createPalette(this, comps); } public Palette(String title, Map<String, Object> components) { this(title, components, null); } public Map<String, Object> getValues() { return values; } /** * The components that belong to the palette. */ public Map<String, Object> getComponents() { return components; } /** * The title that appears at the top of the palette window. */ public String getTitle() { return title; } /** * @jshide */ public boolean hasLabels() { return hasLabels; } /** * Resets the values of the components to their {@link Component#getDefaultValue}. */ public void reset() { for (Object component : components.values()) { if (component instanceof Component) ((Component) component).reset(); } } /** * @jshide */ public Component getComponent(String name) { // components only contains PaletteComponent after initialization, // but is not declared in this way as the passed components object // is reused and PaletteComponent are put pack into it. This gives // easy access to them on the Scripting side. Object component = components.get(name); return component instanceof Component ? (Component) component : null; } private Callable onChange = null; private boolean isChanging = false; /** * The function that is called whenever the value of one of the * {@link Palette#getComponents()} changes. The function receives the * component of which the value has changed as an argument. */ public Callable getOnChange() { return onChange; } public void setOnChange(Callable onChange) { this.onChange = onChange; } protected void onChange(Component component, String name, Object value, boolean callback) { if (!values.containsKey(name)) { // Make sure we observe new fields too. This has to do with the // nature of change observing on JavaScript, where observers can // only be installed for existing properties. // So add a null property under that name now, then register the // observer to make sure it can register. The change after then // trigers straight away. values.put(name, null); ScriptEngine.observeChanges(values, name, this); } isChanging = true; values.put(name, value); isChanging = false; // Use CommitManager functionality to update this dialog once // after all value changes. CommitManager.markDirty(this, this); if (callback && onChange != null) ScriptographerEngine.invoke(onChange, this, component); } protected void onSizeChanged() { sizeChanged = true; // Use CommitManager functionality to update this dialog once // after all value changes. CommitManager.markDirty(this, this); } public void commit(boolean endExecution) { if (proxy != null) proxy.update(sizeChanged); sizeChanged = false; } /** * @jshide */ public void onChangeProperty(Map object, Object key, Object value) { if (!isChanging) { Component component = getComponent(key.toString()); if (component != null) component.setValue(value); } } }