/**
* @(#)AbstractToolBar.java
*
* Copyright (c) 2008 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.samples.svg.gui;
import javax.annotation.Nullable;
import java.awt.*;
import java.beans.*;
import java.util.LinkedList;
import java.util.prefs.*;
import javax.swing.*;
import org.jhotdraw.app.Disposable;
import org.jhotdraw.gui.*;
import org.jhotdraw.draw.*;
import org.jhotdraw.util.prefs.PreferencesUtil;
/**
* AbstractToolBar.
*
* @author Werner Randelshofer
* @version $Id$
*/
public /*abstract*/ class AbstractToolBar extends JDisclosureToolBar implements Disposable {
private static final long serialVersionUID = 1L;
@Nullable protected DrawingEditor editor;
@Nullable private JComponent[] panels;
protected Preferences prefs;
protected PropertyChangeListener eventHandler;
protected LinkedList<Disposable> disposables = new LinkedList<Disposable>();
/** Creates new form. */
public AbstractToolBar() {
initComponents();
try {
prefs = PreferencesUtil.userNodeForPackage(getClass());
} catch (SecurityException e) {
// prefs is null, because we are not permitted to read preferences
}
}
/** This should be an abstract method, but the NetBeans GUI builder
* doesn't support abstract beans.
* @return The ID used to retrieve labels and store user preferences.
*/
protected String getID() {
return "";
}
/** This should be an abstract method, but the NetBeans GUI builder
* doesn't support abstract beans.
*/
protected void init() {
}
protected PropertyChangeListener getEventHandler() {
if (eventHandler == null) {
eventHandler = new PropertyChangeListener() {
@Override
public void propertyChange(PropertyChangeEvent evt) {
String name = evt.getPropertyName();
if (name == DISCLOSURE_STATE_PROPERTY) {
try {
prefs.putInt(getID() + ".disclosureState", (Integer) evt.getNewValue());
} catch (IllegalStateException e) {
// This happens, due to a bug in Apple's implementation
// of the Preferences class.
System.err.println("Warning AbstractToolBar caught IllegalStateException of Preferences class");
e.printStackTrace();
}
}
}
};
}
return eventHandler;
}
public void setEditor(@Nullable DrawingEditor editor) {
if (this.editor != null) {
this.removePropertyChangeListener(getEventHandler());
for (Disposable d : disposables) {
d.dispose();
}
disposables.clear();
}
this.editor = editor;
if (editor != null) {
init();
clearDisclosedComponents();
setDisclosureState(Math.max(0, Math.min(getDisclosureStateCount(), prefs.getInt(getID() + ".disclosureState", getDefaultDisclosureState()))));
this.addPropertyChangeListener(getEventHandler());
}
}
@Nullable public DrawingEditor getEditor() {
return editor;
}
public void clearDisclosedComponents() {
panels = null;
}
@Override
final protected JComponent getDisclosedComponent(int state) {
if (panels == null) {
panels = new JPanel[getDisclosureStateCount()];
for (int i = 0; i < panels.length; i++) {
panels[i] = new ProxyPanel();
}
}
return panels[state];
}
@Nullable
/*abstract*/ protected JComponent createDisclosedComponent(int state) {
return null;
}
protected int getDefaultDisclosureState() {
return 0;
}
@Override
public void dispose() {
for (Disposable d : disposables) {
d.dispose();
}
disposables.clear();
}
private class ProxyPanel extends JPanel {
private static final long serialVersionUID = 1L;
private Runnable runner;
public ProxyPanel() {
setOpaque(false);
setBackground(Color.GREEN);
// The paint method is only called, if the proxy panel is at least
// one pixel wide and high.
setLayout(new FlowLayout(FlowLayout.LEFT, 1, 1));
}
@Override
public void paint(Graphics g) {
super.paint(g);
final int state = getDisclosureState();
if (runner == null) {
runner = new Runnable() {
@Override
public void run() {
try {
panels[state] = createDisclosedComponent(state);
} catch (Throwable t) {
t.printStackTrace();
panels[state] = null;
}
// long end = System.currentTimeMillis();
// System.out.println(AbstractToolBar.this.getClass()+" state:"+state+" elapsed:"+(end-start));
JComponent parent = (JComponent) getParent();
if (parent != null) {
GridBagLayout layout = (GridBagLayout) parent.getLayout();
GridBagConstraints gbc = layout.getConstraints(ProxyPanel.this);
parent.remove(ProxyPanel.this);
if (getDisclosureState() == state) {
if (panels[state] != null) {
parent.add(panels[state], gbc);
} else {
JPanel empty = new JPanel(new BorderLayout());
empty.setOpaque(false);
parent.add(empty, gbc);
}
}
parent.revalidate();
((JComponent) parent.getRootPane().getContentPane()).revalidate();
}
}
};
SwingUtilities.invokeLater(runner);
}
}
}
/** This method is called from within the constructor to
* initialize the form.
* WARNING: Do NOT modify this code. The content of this method is
* always regenerated by the Form Editor.
*/
// <editor-fold defaultstate="collapsed" desc="Generated Code">//GEN-BEGIN:initComponents
private void initComponents() {
}// </editor-fold>//GEN-END:initComponents
// Variables declaration - do not modify//GEN-BEGIN:variables
// End of variables declaration//GEN-END:variables
}