/*
* Copyright 2003-2011 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package jetbrains.mps.nodeEditor.cells;
import jetbrains.mps.editor.runtime.style.StyleAttributes;
import jetbrains.mps.ide.icons.IconLoadHelper;
import jetbrains.mps.nodeEditor.EditorSettings;
import jetbrains.mps.openapi.editor.EditorContext;
import jetbrains.mps.project.AbstractModule;
import jetbrains.mps.util.MacrosFactory;
import jetbrains.mps.vfs.FileSystem;
import org.jetbrains.annotations.Nullable;
import org.jetbrains.mps.openapi.model.SModel;
import org.jetbrains.mps.openapi.model.SNode;
import org.jetbrains.mps.openapi.module.SModule;
import javax.swing.Icon;
import javax.swing.ImageIcon;
import java.awt.FontMetrics;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Image;
import java.awt.Toolkit;
import java.util.HashMap;
import java.util.Map;
public class EditorCell_Image extends EditorCell_Basic {
private static Map<String, Icon> ourIconCache = new HashMap<String, Icon>();
private ImageAlignment myAlignment = ImageAlignment.justify;
private Icon myIcon;
private int myDescent = -1;
protected EditorCell_Image(EditorContext editorContext, SNode node) {
super(editorContext, node);
getStyle().set(StyleAttributes.PUNCTUATION_LEFT, true);
getStyle().set(StyleAttributes.PUNCTUATION_RIGHT, true);
}
public static EditorCell_Image createImageCell(EditorContext editorContext, SNode node, String imageFileName) {
return createImageCell(editorContext, node, getModule(node), imageFileName);
}
@Nullable
private static SModule getModule(SNode node) {
SModel model = node.getModel();
if (model == null) {
return null;
}
return model.getModule();
}
public static EditorCell_Image createImageCell(EditorContext editorContext, SNode node, @Nullable SModule imageModule, String imagePath) {
EditorCell_Image result = new EditorCell_Image(editorContext, node);
result.setIcon(loadIcon(editorContext, imageModule, imagePath));
return result;
}
public static EditorCell_Image createImageCell(EditorContext editorContext, SNode node, Image image) {
EditorCell_Image result = new EditorCell_Image(editorContext, node);
result.setImage(image);
return result;
}
@Override
protected void paintContent(Graphics g, ParentSettings parentSettings) {
if (myIcon == null) {
return;
}
switch (myAlignment) {
case justify: {
if ((myWidth != -1 && myWidth != myIcon.getIconWidth())
|| (myHeight != -1 && myHeight != myIcon.getIconHeight())) {
paintIconScaled(g);
} else {
myIcon.paintIcon(getEditor(), g, myX, myY);
}
break;
}
case center: {
int x = myX + (myWidth - myIcon.getIconWidth()) / 2;
int y = myY + (myHeight - myIcon.getIconHeight()) / 2;
myIcon.paintIcon(getEditor(), g, x, y);
break;
}
case title: {
break;
}
}
}
private void paintIconScaled(Graphics g) {
int iconWidth = myIcon.getIconWidth();
int iconHeight = myIcon.getIconHeight();
if (iconWidth <= 0 || iconHeight <= 0) {
return;
}
double sx = (double) myWidth / (double) iconWidth;
double sy = (double) myHeight / (double) iconHeight;
Graphics2D gscaled = (Graphics2D) g.create();
gscaled.translate(myX, myY);
gscaled.scale(sx, sy);
myIcon.paintIcon(getEditor(), gscaled, 0, 0);
}
@Override
protected void relayoutImpl() {
if (myIcon == null) {
return;
}
if (myAlignment == ImageAlignment.justify) {
int width = myIcon.getIconWidth();
if (width != -1) {
myWidth = width;
}
int height = myIcon.getIconHeight();
if (height != -1) {
myHeight = height;
}
}
if (myDescent < 0) {
myDescent = getFontMetrics().getDescent();
}
}
private FontMetrics getFontMetrics() {
return FontRegistry.getInstance().getFontMetrics(EditorSettings.getInstance().getDefaultEditorFont());
}
@Override
public int getAscent() {
return myHeight - getDescent();
}
@Override
public int getDescent() {
return myDescent >= 0 ? myDescent : 0;
}
public void setDescent(int descent) {
myDescent = descent;
}
public void setAlignment(ImageAlignment alignment) {
myAlignment = alignment;
}
protected void setImageFileName(String fileName) {
if (fileName != null && FileSystem.getInstance().getFileByPath(fileName).exists()) {
setImage(Toolkit.getDefaultToolkit().getImage(fileName));
} else {
setImage(null);
}
}
private static Icon loadIcon(EditorContext context, SModule module, String iconPath) {
String fullPath = MacrosFactory.forModule((AbstractModule) module).expandPath(iconPath);
if (fullPath == null) {
return null;
}
if (!ourIconCache.containsKey(fullPath)){
ourIconCache.put(fullPath, IconLoadHelper.loadIcon(fullPath));
}
return ourIconCache.get(fullPath);
}
@Nullable
private static AbstractModule toAbstractModule(SModule module) {
if (!(module instanceof AbstractModule)) {
return null;
}
return (AbstractModule) module;
}
protected void setImage(Image image) {
setIcon(image == null ? null : new ImageIcon(image));
}
protected void setIcon(Icon icon) {
myIcon = icon;
}
public Icon getIcon() {
return myIcon;
}
public static enum ImageAlignment {
justify, center, title;
}
}