/* -*- tab-width: 4 -*-
*
* Electric(tm) VLSI Design System
*
* File: LayersTab.java
*
* Copyright (c) 2004, Oracle and/or its affiliates. All rights reserved.
*
* Electric(tm) is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 3 of the License, or
* (at your option) any later version.
*
* Electric(tm) is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with Electric(tm); see the file COPYING. If not, write to
* the Free Software Foundation, Inc., 59 Temple Place, Suite 330,
* Boston, Mass 02111-1307, USA.
*/
package com.sun.electric.tool.user.dialogs.options;
import com.sun.electric.database.geometry.EGraphics;
import com.sun.electric.technology.Layer;
import com.sun.electric.technology.Technology;
import com.sun.electric.technology.technologies.Artwork;
import com.sun.electric.tool.user.Resources;
import com.sun.electric.tool.user.User;
import com.sun.electric.tool.user.dialogs.ColorPatternPanel;
import com.sun.electric.tool.user.ui.LayerVisibility;
import com.sun.electric.tool.user.ui.WindowFrame;
import com.sun.electric.util.TextUtils;
import java.awt.Color;
import java.awt.Frame;
import java.awt.GridBagConstraints;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import javax.swing.JPanel;
/**
* Class to handle the "Colors and Layers" tab of the Preferences dialog.
*/
public class LayersTab extends PreferencePanel
{
private Map<Layer,ColorPatternPanel.Info> layerMap;
private Map<String,ColorPatternPanel.Info> transAndSpecialMap;
private Map<User.ColorPrefType, String> nameTypeSpecialMap;
private Map<Technology,Color []> colorMapMap;
private ColorPatternPanel colorAndPatternPanel;
private Layer defaultArtworkLayer;
private final static String DEFAULT_ARTWORK = "Special: DEFAULT ARTWORK";
private void resetColorPanelInfo(ColorPatternPanel.Info cpi)
{
int factoryColor = -1;
if (cpi.graphics != null)
{
cpi.useStippleDisplay = cpi.graphics.isPatternedOnDisplay();
cpi.useStipplePrinter = cpi.graphics.isPatternedOnPrinter();
cpi.outlinePatternDisplay = cpi.graphics.getOutlined();
cpi.transparentLayer = cpi.graphics.getTransparentLayer();
cpi.pattern = cpi.graphics.getPattern();
cpi.opacity = cpi.graphics.getOpacity();
factoryColor = cpi.graphics.getColor().getRGB(); // color given by graphics for the rest of layers
}
else
factoryColor = cpi.theColor.getFactoryDefaultColor().getRGB(); // factory color for special layers
cpi.red = (factoryColor>>16) & 0xFF;
cpi.green = (factoryColor>>8) & 0xFF;
cpi.blue = factoryColor & 0xFF;
}
/** Creates new form LayerTab */
public LayersTab(Frame parent, boolean modal)
{
super(parent, modal);
initComponents();
// make the color/pattern panel
colorAndPatternPanel = new ColorPatternPanel(true);
GridBagConstraints gbc = new GridBagConstraints();
gbc.gridx = 0; gbc.gridy = 1;
gbc.weightx = 1; gbc.weighty = 1;
gbc.gridwidth = 4; gbc.gridheight = 1;
gbc.insets = new java.awt.Insets(4, 4, 4, 4);
layers.add(colorAndPatternPanel, gbc);
layerMap = new HashMap<Layer,ColorPatternPanel.Info>();
transAndSpecialMap = new HashMap<String,ColorPatternPanel.Info>();
nameTypeSpecialMap = new HashMap<User.ColorPrefType, String>();
colorMapMap = new HashMap<Technology,Color []>();
layerName.addActionListener(new ActionListener()
{
public void actionPerformed(ActionEvent evt) { layerSelected(); }
});
for(Iterator<Technology> it = Technology.getTechnologies(); it.hasNext(); )
{
Technology tech = it.next();
technology.addItem(tech.getTechName());
}
technology.addActionListener(new ActionListener()
{
public void actionPerformed(ActionEvent evt) { setTechnology(); }
});
}
/** return the panel to use for user preferences. */
public JPanel getUserPreferencesPanel() { return layers; }
/** return the name of this preferences tab. */
public String getName() { return "Layers"; }
/**
* Method called at the start of the dialog.
* Caches current values and displays them in the tab.
*/
public void init()
{
// make a map of all layers
for(Iterator<Technology> it = Technology.getTechnologies(); it.hasNext(); )
{
Technology tech = it.next();
for(Iterator<Layer> lIt = tech.getLayers(); lIt.hasNext(); )
{
Layer layer = lIt.next();
if (layer.isPseudoLayer() && layer.getNonPseudoLayer() != layer) continue;
// layerName.addItem(layer.getName());
if (tech instanceof Artwork) {
assert layer.getName().equals("Graphics");
defaultArtworkLayer = layer;
}
// ColorPatternPanel.Info li = new ColorPatternPanel.Info(layer.getGraphics());
// layerMap.put(layer, li);
}
// // make an entry for the technology's color map
// Color [] map = tech.getTransparentLayerColors();
// colorMapMap.put(tech, map);
}
// add the special layers
nameTypeSpecialMap.put(User.ColorPrefType.BACKGROUND, "Special: BACKGROUND");
nameTypeSpecialMap.put(User.ColorPrefType.GRID, "Special: GRID");
nameTypeSpecialMap.put(User.ColorPrefType.MEASUREMENT, "Special: MEASUREMENT");
nameTypeSpecialMap.put(User.ColorPrefType.HIGHLIGHT, "Special: HIGHLIGHT");
nameTypeSpecialMap.put(User.ColorPrefType.NODE_HIGHLIGHT, "Special: NODE HIGHLIGHT");
nameTypeSpecialMap.put(User.ColorPrefType.MOUSEOVER_HIGHLIGHT, "Special: MOUSE-OVER HIGHLIGHT");
nameTypeSpecialMap.put(User.ColorPrefType.PORT_HIGHLIGHT, "Special: PORT HIGHLIGHT");
nameTypeSpecialMap.put(User.ColorPrefType.TEXT, "Special: TEXT");
nameTypeSpecialMap.put(User.ColorPrefType.INSTANCE, "Special: INSTANCE OUTLINES");
nameTypeSpecialMap.put(User.ColorPrefType.DOWNINPLACEBORDER, "Special: DOWN-IN-PLACE BORDER");
nameTypeSpecialMap.put(User.ColorPrefType.WAVE_BACKGROUND, "Special: WAVEFORM BACKGROUND");
nameTypeSpecialMap.put(User.ColorPrefType.WAVE_FOREGROUND, "Special: WAVEFORM FOREGROUND");
nameTypeSpecialMap.put(User.ColorPrefType.WAVE_STIMULI, "Special: WAVEFORM STIMULI");
nameTypeSpecialMap.put(User.ColorPrefType.WAVE_OFF_STRENGTH, "Special: WAVEFORM OFF STRENGTH");
nameTypeSpecialMap.put(User.ColorPrefType.WAVE_NODE_STRENGTH, "Special: WAVEFORM NODE (WEAK) STRENGTH");
nameTypeSpecialMap.put(User.ColorPrefType.WAVE_GATE_STRENGTH, "Special: WAVEFORM GATE STRENGTH");
nameTypeSpecialMap.put(User.ColorPrefType.WAVE_POWER_STRENGTH, "Special: WAVEFORM POWER STRENGTH");
nameTypeSpecialMap.put(User.ColorPrefType.WAVE_CROSS_LOW, "Special: WAVEFORM CROSSPROBE LOW");
nameTypeSpecialMap.put(User.ColorPrefType.WAVE_CROSS_HIGH, "Special: WAVEFORM CROSSPROBE HIGH");
nameTypeSpecialMap.put(User.ColorPrefType.WAVE_CROSS_UNDEF, "Special: WAVEFORM CROSSPROBE UNDEFINED");
nameTypeSpecialMap.put(User.ColorPrefType.WAVE_CROSS_FLOAT, "Special: WAVEFORM CROSSPROBE FLOATING");
// 3D Stuff
try
{
Class<?> j3DUtilsClass = Resources.get3DClass("utils.J3DUtils");
if (j3DUtilsClass != null)
{
Method setMethod = j3DUtilsClass.getDeclaredMethod("get3DColorsInTab", new Class[] {Map.class});
setMethod.invoke(j3DUtilsClass, new Object[]{nameTypeSpecialMap});
}
// else System.out.println("Cannot call 3D plugin method get3DColorsInTab");
} catch (Exception e) {
System.out.println("Error calling 3D plugin method get3DColorsInTab");
e.printStackTrace();
}
cacheLayerInfo(false);
// for (Map.Entry<User.ColorPrefType,String> e: nameTypeSpecialMap.entrySet())
// {
// User.ColorPrefType type = e.getKey();
// String title = e.getValue();
// transAndSpecialMap.put(title, new ColorPatternPanel.Info(type));
// }
technology.setSelectedItem(Technology.getCurrent().getTechName());
}
public void cacheLayerInfo(boolean redraw)
{
for(Iterator<Technology> it = Technology.getTechnologies(); it.hasNext(); )
{
Technology tech = it.next();
for(Iterator<Layer> lIt = tech.getLayers(); lIt.hasNext(); )
{
Layer layer = lIt.next();
if (layer.isPseudoLayer() && layer.getNonPseudoLayer() != layer) continue;
ColorPatternPanel.Info li = new ColorPatternPanel.Info(layer.getGraphics());
layerMap.put(layer, li);
}
// make an entry for the technology's color map
Color [] map = tech.getTransparentLayerColors();
colorMapMap.put(tech, map);
}
for (Map.Entry<User.ColorPrefType,String> e: nameTypeSpecialMap.entrySet())
{
User.ColorPrefType type = e.getKey();
String title = e.getValue();
transAndSpecialMap.put(title, new ColorPatternPanel.Info(type));
}
if (redraw) layerSelected();
}
/**
* Method called when the Technology popup changes.
*/
private void setTechnology()
{
String techName = (String)technology.getSelectedItem();
Technology tech = Technology.findTechnology(techName);
if (tech == null) return;
// report the map for the technology
Color [] map = colorMapMap.get(tech);
colorAndPatternPanel.setColorMap(map);
layerName.removeAllItems();
// add all layers in the technology
for(Iterator<Layer> lIt = tech.getLayers(); lIt.hasNext(); )
{
Layer layer = lIt.next();
if (layer.isPseudoLayer() && layer.getNonPseudoLayer() != layer) continue;
layerName.addItem(layer.getName());
}
// add special layer names
List<String> specialList = new ArrayList<String>();
specialList.add(DEFAULT_ARTWORK);
for(String name : transAndSpecialMap.keySet())
specialList.add(name);
Collections.sort(specialList, TextUtils.STRING_NUMBER_ORDER);
for(String name : specialList)
{
layerName.addItem(name);
}
layerSelected();
}
/**
* Method called when the Layer popup changes.
*/
private void layerSelected()
{
String techName = (String)technology.getSelectedItem();
Technology tech = Technology.findTechnology(techName);
if (tech == null) return;
String name = (String)layerName.getSelectedItem();
if (name == null) return;
ColorPatternPanel.Info li = transAndSpecialMap.get(name);
Layer layer = null;
if (li == null)
{
layer = name.equals(DEFAULT_ARTWORK) ? defaultArtworkLayer : tech.findLayer(name);
li = layerMap.get(layer);
}
if (li == null) return;
colorAndPatternPanel.setColorPattern(li);
// see if this layer is transparent and shares with another layer
String otherLayers = null;
if (li.transparentLayer > 0 && layer != null)
{
for(Iterator<Layer> it = tech.getLayers(); it.hasNext(); )
{
Layer oLayer = it.next();
if (oLayer == layer) continue;
ColorPatternPanel.Info oLi = layerMap.get(oLayer);
if (oLi != null && oLi.transparentLayer == li.transparentLayer)
{
if (otherLayers == null) otherLayers = oLayer.getName(); else
otherLayers += ", " + oLayer.getName();
}
}
}
colorAndPatternPanel.setOtherTransparentLayerNames(otherLayers);
}
/**
* Method called when the "OK" panel is hit.
* Updates any changed fields in the Layers tab.
*/
public void term()
{
boolean changed = false;
for(Iterator<Technology> it = Technology.getTechnologies(); it.hasNext(); )
{
Technology tech = it.next();
for(Iterator<Layer> lIt = tech.getLayers(); lIt.hasNext(); )
{
Layer layer = lIt.next();
ColorPatternPanel.Info li = layerMap.get(layer);
EGraphics graphics = layer.getGraphics();
if (layer.isPseudoLayer())
{
ColorPatternPanel.Info altLI = layerMap.get(layer.getNonPseudoLayer());
if (altLI != null) li = altLI;
}
EGraphics newGraphics = li.updateGraphics(graphics);
if (newGraphics != graphics)
{
changed = true;
layer.setGraphics(newGraphics);
}
}
// determine the original colors for this technology
Color [] origMap = tech.getTransparentLayerColors();
// see if any colors changed
boolean mapChanged = false;
Color [] map = colorMapMap.get(tech);
for(int i=0; i<map.length; i++)
if (map[i].getRGB() != origMap[i].getRGB()) mapChanged = true;
if (mapChanged)
tech.setColorMapFromLayers(map);
}
// also get any changes to special layers
for (Map.Entry<User.ColorPrefType,String> e: nameTypeSpecialMap.entrySet())
{
User.ColorPrefType type = e.getKey();
String title = e.getValue();
int c = specialMapColor(title, User.getColor(type));
if (c >= 0)
{
User.setColor(type, c);
changed = true;
}
}
// redisplay if changes were made
if (changed)
{
WindowFrame.repaintAllWindows();
}
}
/**
* Method called when the factory reset is requested for just this panel.
* @return true if the panel can be reset "in place" without redisplay.
*/
public boolean resetThis()
{
for(Layer layer : layerMap.keySet())
{
ColorPatternPanel.Info cpi = layerMap.get(layer);
resetColorPanelInfo(cpi);
}
// Special layers
for(ColorPatternPanel.Info cpi: transAndSpecialMap.values())
{
resetColorPanelInfo(cpi);
}
for(Iterator<Technology> it = Technology.getTechnologies(); it.hasNext(); )
{
Technology tech = it.next();
Color [] map = tech.getFactoryTransparentLayerColors();
colorMapMap.put(tech, map);
}
colorAndPatternPanel.setColorPattern(null);
setTechnology();
return true;
}
/**
* Method called when the factory reset is requested.
*/
public void reset()
{
for(Iterator<Technology> it = Technology.getTechnologies(); it.hasNext(); )
{
Technology tech = it.next();
// reload color map for technology if necessary
Color [] transColorsFactory = tech.getFactoryTransparentLayerColors();
Color [] transColors = tech.getTransparentLayerColors();
boolean reload = transColorsFactory.length != transColors.length;
if (!reload)
{
for(int i=0; i<transColors.length; i++)
if (transColorsFactory[i].getRGB() != transColors[i].getRGB()) reload = true;
}
if (reload)
tech.setColorMapFromLayers(transColorsFactory);
// reload individual layer graphics
for(Iterator<Layer> lIt = tech.getLayers(); lIt.hasNext(); )
{
Layer layer = lIt.next();
if (layer.isPseudoLayer() && layer.getNonPseudoLayer() != layer) continue;
layer.setGraphics(layer.getFactoryGraphics());
}
}
LayerVisibility.factoryReset();
// Special layers
for (User.ColorPrefType type : nameTypeSpecialMap.keySet())
{
String name = nameTypeSpecialMap.get(type);
ColorPatternPanel.Info cpi = transAndSpecialMap.get(name);
int factory = cpi.theColor.getFactoryDefaultColor().getRGB() & 0xFFFFFF;
if (factory != User.getColor(cpi.theColor))
{
User.setColor(type, factory);
}
}
}
public int specialMapColor(String title, int curColor)
{
ColorPatternPanel.Info li = transAndSpecialMap.get(title);
if (li == null) return -1;
int newColor = (li.red << 16) | (li.green << 8) | li.blue;
if (newColor != curColor) return newColor;
return -1;
}
/** 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()
{
java.awt.GridBagConstraints gridBagConstraints;
layers = new javax.swing.JPanel();
layerName = new javax.swing.JComboBox();
layerTechName = new javax.swing.JLabel();
technology = new javax.swing.JComboBox();
layerTechName1 = new javax.swing.JLabel();
getContentPane().setLayout(new java.awt.GridBagLayout());
setTitle("Edit Options");
setName("");
addWindowListener(new java.awt.event.WindowAdapter()
{
public void windowClosing(java.awt.event.WindowEvent evt)
{
closeDialog(evt);
}
});
layers.setLayout(new java.awt.GridBagLayout());
gridBagConstraints = new java.awt.GridBagConstraints();
gridBagConstraints.gridx = 3;
gridBagConstraints.gridy = 0;
gridBagConstraints.fill = java.awt.GridBagConstraints.HORIZONTAL;
gridBagConstraints.weightx = 0.5;
gridBagConstraints.insets = new java.awt.Insets(4, 4, 4, 4);
layers.add(layerName, gridBagConstraints);
layerTechName.setText("Layer:");
gridBagConstraints = new java.awt.GridBagConstraints();
gridBagConstraints.gridx = 2;
gridBagConstraints.gridy = 0;
gridBagConstraints.anchor = java.awt.GridBagConstraints.WEST;
gridBagConstraints.insets = new java.awt.Insets(4, 4, 4, 4);
layers.add(layerTechName, gridBagConstraints);
gridBagConstraints = new java.awt.GridBagConstraints();
gridBagConstraints.gridx = 1;
gridBagConstraints.gridy = 0;
gridBagConstraints.fill = java.awt.GridBagConstraints.HORIZONTAL;
gridBagConstraints.weightx = 0.5;
gridBagConstraints.insets = new java.awt.Insets(4, 4, 4, 4);
layers.add(technology, gridBagConstraints);
layerTechName1.setText("Technology:");
gridBagConstraints = new java.awt.GridBagConstraints();
gridBagConstraints.gridx = 0;
gridBagConstraints.gridy = 0;
gridBagConstraints.anchor = java.awt.GridBagConstraints.WEST;
gridBagConstraints.insets = new java.awt.Insets(4, 4, 4, 4);
layers.add(layerTechName1, gridBagConstraints);
getContentPane().add(layers, new java.awt.GridBagConstraints());
pack();
}// </editor-fold>//GEN-END:initComponents
/** Closes the dialog */
private void closeDialog(java.awt.event.WindowEvent evt)//GEN-FIRST:event_closeDialog
{
setVisible(false);
dispose();
}//GEN-LAST:event_closeDialog
// Variables declaration - do not modify//GEN-BEGIN:variables
private javax.swing.JComboBox layerName;
private javax.swing.JLabel layerTechName;
private javax.swing.JLabel layerTechName1;
private javax.swing.JPanel layers;
private javax.swing.JComboBox technology;
// End of variables declaration//GEN-END:variables
}