/*******************************************************************************
* Copyright (c) 2006-2012
* Software Technology Group, Dresden University of Technology
* DevBoost GmbH, Berlin, Amtsgericht Charlottenburg, HRB 140026
*
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* Software Technology Group - TU Dresden, Germany;
* DevBoost GmbH - Berlin, Germany
* - initial API and implementation
******************************************************************************/
/*
* @(#)DefaultDrawingEditor.java 3.2.2 2008-06-08
*
* Copyright (c) 1996-2008 by the original authors of JHotDraw
* and all its contributors.
* All rights reserved.
*
* The copyright of this software is owned by the authors and
* contributors of the JHotDraw project ("the copyright holders").
* You may not use, copy or modify this software, except in
* accordance with the license agreement you entered into with
* the copyright holders. For details see accompanying license terms.
*/
package org.jhotdraw.draw;
import org.jhotdraw.beans.*;
import java.awt.*;
import java.awt.datatransfer.*;
import java.awt.event.FocusEvent;
import java.awt.event.FocusListener;
import java.beans.*;
import java.util.*;
import java.io.*;
import javax.swing.JComponent;
import static org.jhotdraw.draw.AttributeKeys.*;
/**
* DefaultDrawingEditor.
* <p>
* Design pattern:<br>
* Name: Proxy.<br>
* Role: Subject.<br>
* Partners: {@link org.jhotdraw.draw.action.DrawingEditorProxy} as Proxy, {@link DrawingEditor} as
* Subject.
*
* @author Werner Randelshofer
* @version 3.2.2 Method getActiveView must fires now a PropertyChangeEvent, if
* it automatically activates the first view of the editor.
* <br>3.2.1 2008-04-12 Method getDefaultAttribute returns default value of
* AttributeKey when the AttributeKey is not in the attribute map.
* <br>3.2 2007-04-22 Keep last focus view, even if we lost focus permanently.
* <br>3.1 2007-04-16 Added method getDefaultAttributes.
* <br>3.0 2006-02-13 Revised to handle multiple drawing views.
* <br>1.0 2003-12-01 Derived from JHotDraw 5.4b1.
*/
public class DefaultDrawingEditor extends AbstractBean implements DrawingEditor, ToolListener {
private HashMap<AttributeKey, Object> defaultAttributes = new HashMap<AttributeKey, Object>();
private HashMap<AttributeKey, Object> handleAttributes = new HashMap<AttributeKey, Object>();
private Tool tool;
private HashSet<DrawingView> views;
private DrawingView activeView;
private boolean isEnabled = true;
private FocusListener focusHandler = new FocusListener() {
public void focusGained(FocusEvent e) {
setActiveView((DrawingView) findView((Container) e.getSource()));
}
public void focusLost(FocusEvent e) {
/*
if (! e.isTemporary()) {
setFocusedView(null);
}*/
}
};
/** Creates a new instance. */
public DefaultDrawingEditor() {
setDefaultAttribute(FILL_COLOR, Color.white);
setDefaultAttribute(STROKE_COLOR, Color.black);
setDefaultAttribute(TEXT_COLOR, Color.black);
views = new HashSet<DrawingView>();
}
public void setTool(Tool newValue) {
Tool oldValue = tool;
if (newValue == tool) {
return;
}
if (tool != null) {
for (DrawingView v : views) {
v.removeMouseListener(tool);
v.removeMouseMotionListener(tool);
v.removeKeyListener(tool);
}
tool.deactivate(this);
tool.removeToolListener(this);
}
tool = newValue;
if (tool != null) {
tool.activate(this);
for (DrawingView v : views) {
v.addMouseListener(tool);
v.addMouseMotionListener(tool);
v.addKeyListener(tool);
}
tool.addToolListener(this);
}
firePropertyChange(TOOL_PROPERTY, oldValue, newValue);
}
public void areaInvalidated(ToolEvent evt) {
Rectangle r = evt.getInvalidatedArea();
evt.getView().getComponent().repaint(r.x, r.y, r.width, r.height);
}
private Dimension preferredViewSize;
public void toolStarted(ToolEvent evt) {
setActiveView(evt.getView());
}
public void setActiveView(DrawingView newValue) {
DrawingView oldValue = activeView;
activeView = newValue;
if (newValue != null && newValue != oldValue) {
preferredViewSize = activeView.getComponent().getPreferredSize();
}
firePropertyChange(ACTIVE_VIEW_PROPERTY, oldValue, newValue);
}
public void toolDone(ToolEvent evt) {
// XXX - Maybe we should do this with all views of the editor??
DrawingView v = getActiveView();
if (v != null) {
JComponent c = v.getComponent();
Dimension oldPreferredViewSize = preferredViewSize;
preferredViewSize = c.getPreferredSize();
if (oldPreferredViewSize == null || !oldPreferredViewSize.equals(preferredViewSize)) {
c.revalidate();
}
}
}
public Tool getTool() {
return tool;
}
public DrawingView getActiveView() {
if (activeView == null && views.size() != 0) {
setActiveView(views.iterator().next());
}
return activeView;
}
private void updateActiveView() {
for (DrawingView v : views) {
if (v.getComponent().isFocusOwner()) {
setActiveView(v);
return;
}
}
setActiveView(null);
}
@SuppressWarnings("unchecked")
public void applyDefaultAttributesTo(Figure f) {
for (Map.Entry<AttributeKey, Object> entry : defaultAttributes.entrySet()) {
entry.getKey().basicSet(f, entry.getValue());
}
}
public <T> T getDefaultAttribute(AttributeKey<T> key) {
if (defaultAttributes.containsKey(key)) {
return key.get(defaultAttributes);
} else {
return key.getDefaultValue();
}
}
public void setDefaultAttribute(AttributeKey key, Object newValue) {
Object oldValue = defaultAttributes.put(key, newValue);
firePropertyChange(key.getKey(), oldValue, newValue);
}
public void remove(DrawingView view) {
view.getComponent().removeFocusListener(focusHandler);
views.remove(view);
if (tool != null) {
view.removeMouseListener(tool);
view.removeMouseMotionListener(tool);
view.removeKeyListener(tool);
}
view.removeNotify(this);
if (activeView == view) {
view = (views.size() > 0) ? views.iterator().next() : null;
}
updateActiveView();
}
public void add(DrawingView view) {
views.add(view);
view.addNotify(this);
view.getComponent().addFocusListener(focusHandler);
if (tool != null) {
view.addMouseListener(tool);
view.addMouseMotionListener(tool);
view.addKeyListener(tool);
}
updateActiveView();
}
public void setCursor(Cursor c) {
}
public Collection<DrawingView> getDrawingViews() {
return Collections.unmodifiableCollection(views);
}
public DrawingView findView(Container c) {
for (DrawingView v : views) {
if (v.getComponent() == c) {
return v;
}
}
return null;
}
public void setEnabled(boolean newValue) {
if (newValue != isEnabled) {
boolean oldValue = isEnabled;
isEnabled = newValue;
firePropertyChange("enabled", oldValue, newValue);
}
}
public boolean isEnabled() {
return isEnabled;
}
public Map<AttributeKey, Object> getDefaultAttributes() {
return Collections.unmodifiableMap(defaultAttributes);
}
public void setHandleAttribute(AttributeKey key, Object value) {
handleAttributes.put(key, value);
}
public <T> T getHandleAttribute(AttributeKey<T> key) {
if (handleAttributes.containsKey(key)) {
return key.get(handleAttributes);
} else {
return key.getDefaultValue();
}
}
}