/* * @(#)ProjectPropertyAction.java * * Copyright (c) 1996-2010 The authors and contributors of JHotDraw. * You may not use, copy or modify this file, except in compliance with the * accompanying license terms. */ package org.jhotdraw.app.action.view; import edu.umd.cs.findbugs.annotations.Nullable; import java.awt.event.*; import java.beans.*; import org.jhotdraw.app.Application; import org.jhotdraw.app.View; import org.jhotdraw.app.action.AbstractViewAction; import org.jhotdraw.app.action.ActionUtil; /** * ToggleViewPropertyAction. * * @author Werner Randelshofer. * @version $Id$ */ public class ToggleViewPropertyAction extends AbstractViewAction { private static final long serialVersionUID = 1L; final private String propertyName; private Class<?>[] parameterClass; private Object selectedPropertyValue; private Object deselectedPropertyValue; final private String setterName; final private String getterName; private PropertyChangeListener viewListener = new PropertyChangeListener() { @Override public void propertyChange(PropertyChangeEvent evt) { if (propertyName.equals(evt.getPropertyName())) { // Strings get interned updateView(); } } }; /** Creates a new instance. */ public ToggleViewPropertyAction(Application app, @Nullable View view, String propertyName) { this(app, view, propertyName, Boolean.TYPE, true, false); } public ToggleViewPropertyAction(Application app, @Nullable View view, String propertyName, Class<?> propertyClass, Object selectedPropertyValue, Object deselectedPropertyValue) { super(app, view); if (propertyName==null) { throw new IllegalArgumentException("Parameter propertyName must not be null"); } this.propertyName = propertyName; this.parameterClass = new Class<?>[] { propertyClass }; this.selectedPropertyValue = selectedPropertyValue; this.deselectedPropertyValue = deselectedPropertyValue; setterName = "set"+Character.toUpperCase(propertyName.charAt(0)) + propertyName.substring(1); getterName = ((propertyClass == Boolean.TYPE || propertyClass == Boolean.class) ? "is" : "get")+ Character.toUpperCase(propertyName.charAt(0)) + propertyName.substring(1); updateView(); } @Override public void actionPerformed(ActionEvent evt) { View p = getActiveView(); Object value = getCurrentValue(); Object newValue = (value == selectedPropertyValue || value != null && selectedPropertyValue != null && value.equals(selectedPropertyValue)) ? deselectedPropertyValue : selectedPropertyValue; try { p.getClass().getMethod(setterName, parameterClass).invoke(p, new Object[] {newValue}); } catch (Throwable e) { InternalError error = new InternalError("No "+setterName+" method on "+p); error.initCause(e); throw error; } } @Nullable private Object getCurrentValue() { View p = getActiveView(); if (p != null) { try { return p.getClass().getMethod(getterName, (Class[]) null).invoke(p); } catch (Throwable e) { InternalError error = new InternalError("No "+getterName+" method on "+p); error.initCause(e); throw error; } } return null; } @Override protected void installViewListeners(View p) { super.installViewListeners(p); p.addPropertyChangeListener(viewListener); updateView(); } /** * Installs listeners on the view object. */ @Override protected void uninstallViewListeners(View p) { super.uninstallViewListeners(p); p.removePropertyChangeListener(viewListener); } @Override protected void updateView() { if (getterName == null) { // This happens, when updateView is called before the constructor // has been completed. return; } boolean isSelected = false; View p = getActiveView(); if (p != null) { try { Object value = p.getClass().getMethod(getterName, (Class[]) null).invoke(p); isSelected = value == selectedPropertyValue || value != null && selectedPropertyValue != null && value.equals(selectedPropertyValue); } catch (Throwable e) { InternalError error = new InternalError("No "+getterName+" method on "+p+" for property "+propertyName); error.initCause(e); throw error; } } putValue(ActionUtil.SELECTED_KEY, isSelected); } }