TileMangler/src/tm/ui/TMPalettePane.java

455 lines
No EOL
13 KiB
Java

/*
*
* Copyright (C) 2003 Kent Hansen.
*
* This file is part of Tile Mangler.
*
* Tile Mangler 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 2 of the License, or
* (at your option) any later version.
*
* Tile Mangler 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.
*
*/
/**
* 2014-05-06
* Added the shift palette functionality
* Mewster
*/
package tm.ui;
import tm.TMPalette;
import tm.colorcodecs.ColorCodec;
import tm.utils.DecimalNumberVerifier;
import javax.swing.*;
import javax.swing.event.*;
import java.awt.*;
import java.awt.event.*;
import javax.swing.border.*;
/**
*
* The palette pane contains the following components:
* - Foreground color box
* - Background color box
* - Palette vizualiser (see TMPaletteVizualiser)
* - FG/BG swap button
* - Arrow up/down for switching palette index
*
**/
public class TMPalettePane extends JPanel implements MouseInputListener {
private TMView view;
private TMUI ui;
private TMPaletteVizualiser vizualiser = new TMPaletteVizualiser();
private ColorBox fgColorBox = new ColorBox();
private ColorBox bgColorBox = new ColorBox();
ClassLoader cl = getClass().getClassLoader();
private Cursor pickupCursor = Toolkit.getDefaultToolkit().createCustomCursor(new ImageIcon(cl.getResource("tm/icons/DropperCursor24.gif")).getImage(), new Point(8,23), "Dropper");
private JButton decButton = new JButton(new ImageIcon(cl.getResource("tm/icons/original/DecPalIndex24.gif")));
private JButton incButton = new JButton(new ImageIcon(cl.getResource("tm/icons/original/IncPalIndex24.gif")));
private JButton leftShiftButton = new JButton(new ImageIcon(cl.getResource("tm/icons/original/DecPalIndex24.gif")));
private JButton rightShiftButton = new JButton(new ImageIcon(cl.getResource("tm/icons/original/IncPalIndex24.gif")));
private JButton swapButton = new JButton(new ImageIcon(cl.getResource("tm/icons/original/Swap24.gif")));
private JTextField shiftValueField = new JTextField("1");
/**
*
* Creates a palette pane.
*
**/
public TMPalettePane(TMUI ui) {
boolean DarkIcons = TMUI.DarkIcons;
if(DarkIcons){
decButton.setIcon(new ImageIcon(cl.getResource("tm/icons/original/DecPalIndex24.gif")));
incButton.setIcon(new ImageIcon(cl.getResource("tm/icons/original/IncPalIndex24.gif")));
leftShiftButton.setIcon(new ImageIcon(cl.getResource("tm/icons/original/DecPalIndex24.gif")));
rightShiftButton.setIcon(new ImageIcon(cl.getResource("tm/icons/original/IncPalIndex24.gif")));
swapButton.setIcon(new ImageIcon(cl.getResource("tm/icons/original/Swap24.gif")));
}
this.ui = ui;
vizualiser = new TMPaletteVizualiser();
//setBorder(new EtchedBorder(EtchedBorder.RAISED));
swapButton.setBorder(null);
// set up UI
setLayout(null); // no layout manager, want to place and size components pixel-perfect
shiftValueField.addKeyListener(new DecimalNumberVerifier());
// add components
add(fgColorBox);
add(bgColorBox);
add(swapButton);
add(vizualiser);
add(decButton);
add(incButton);
add(leftShiftButton);
add(rightShiftButton);
add(shiftValueField);
// set sizes
fgColorBox.setSize(32, 32);
bgColorBox.setSize(32, 32);
swapButton.setSize(32, 32);
vizualiser.setSize(256, 64);
decButton.setSize(32, 64);
incButton.setSize(32, 64);
leftShiftButton.setSize(32, 32);
rightShiftButton.setSize(32, 32);
shiftValueField.setSize(64, 20);
// set positions
fgColorBox.setLocation(8, 8);
bgColorBox.setLocation(40, 40);
swapButton.setLocation(8, 40);
decButton.setLocation(80, 8);
vizualiser.setLocation(112, 8);
incButton.setLocation(368, 8);
leftShiftButton.setLocation(420, 24);
shiftValueField.setLocation(460, 30);
rightShiftButton.setLocation(530, 24);
vizualiser.setCursor(pickupCursor);
vizualiser.addMouseListener(this);
swapButton.setFocusable(false);
swapButton.addActionListener(
new ActionListener() {
public void actionPerformed(ActionEvent e) {
swapColors();
}
}
);
decButton.setFocusable(false);
decButton.addActionListener(
new ActionListener() {
public void actionPerformed(ActionEvent e) {
setPreviousPalIndex();
}
}
);
incButton.setFocusable(false);
incButton.addActionListener(
new ActionListener() {
public void actionPerformed(ActionEvent e) {
setNextPalIndex();
}
}
);
leftShiftButton.setFocusable(false);
leftShiftButton.addActionListener(
new ActionListener() {
public void actionPerformed(ActionEvent e) {
shiftPalette(-getShift());
}
}
);
rightShiftButton.setFocusable(false);
rightShiftButton.addActionListener(
new ActionListener() {
public void actionPerformed(ActionEvent e) {
shiftPalette(+getShift());
}
}
);
lockShiftButtons();
setPreferredSize(new Dimension(2048, 80));
}
/**
*
* Sets the palette to be rendered.
*
**/
public void setPalette(TMPalette palette) {
if (palette.isDirect()) { lockShiftButtons(); }
else { unlockShiftButtons(); }
vizualiser.setPalette(palette);
}
/**
*
* Sets the palette index from which to start displaying colors.
*
**/
public void setPalIndex(int palIndex) {
vizualiser.setPalIndex(palIndex);
}
/**
*
* Sets the bitdepth, i.e. how many colors to display.
*
**/
public void setBitDepth(int bitDepth) {
vizualiser.setBitDepth(bitDepth);
}
/**
*
* Sets the foreground color.
*
**/
public void setFGColor(int fgColor) {
fgColorBox.setColor(fgColor);
}
/**
*
* Sets the background color.
*
**/
public void setBGColor(int bgColor) {
bgColorBox.setColor(bgColor);
}
/**
*
* Called when a view has been selected.
* Loads and displays the view's palette according to current settings.
*
**/
public void viewSelected(TMView view) {
this.view = view;
// get view palette,color settings
setPalette(view.getPalette());
setPalIndex(view.getPalIndex());
setBitDepth(view.getTileCodec().getBitsPerPixel());
setFGColor(view.getFGColor());
setBGColor(view.getBGColor());
repaint();
}
/**
*
* Called when user clicked on a color.
* Set the color as foreground or background color depending on which button was pressed.
*
**/
public void mousePressed(MouseEvent e) {
// get the color
int color = vizualiser.getColorAt(e.getX(), e.getY());
// set it
if (e.getButton() == MouseEvent.BUTTON1) {
// set as foreground color
ui.setFGColor(color);
}
else {
// set as background color
ui.setBGColor(color);
}
}
// Other mouse events, not used yet...
public void mouseClicked(MouseEvent e) {
if (e.getClickCount() == 2) {
// let user edit the color
Color newColor = JColorChooser.showDialog(ui, "Edit Color", new Color(fgColorBox.getColor()));
if (newColor != null) {
boolean equal = view.getFGColor() == view.getBGColor();
int rgb = newColor.getRGB();
int colorIndex = vizualiser.getIndexOfColorAt(e.getX(), e.getY());
TMPalette palette = view.getPalette();
/* view.addReversibleAction(
new ReversiblePaletteEditAction(
view,
palette,
colorIndex,
palette.getEntryRGB(colorIndex),
rgb
)
;*/
// set the new color(s)
palette.setEntryRGB(colorIndex, rgb);
ui.setFGColor(palette.getEntryRGB(colorIndex));
if (equal) {
ui.setBGColor(palette.getEntryRGB(colorIndex));
}
// PS: If palette is NOT direct then this means fileimage.modified!!
if (!palette.isDirect()) {
byte[] src = palette.getEntryBytes(colorIndex);
byte[] dest = view.getFileImage().getContents();
System.arraycopy(src, 0, dest, palette.getOffset()+(colorIndex*src.length), src.length);
ui.fileImageModified(view.getFileImage());
}
// redraw stuff
view.getEditorCanvas().unpackPixels();
view.getEditorCanvas().redraw();
repaint();
}
}
}
public void mouseDragged(MouseEvent e) { }
public void mouseMoved(MouseEvent e) { }
public void mouseEntered(MouseEvent e) { }
public void mouseExited(MouseEvent e) { }
public void mouseReleased(MouseEvent e) { }
/**
*
* A "color box" is merely a label that is painted with a color.
*
**/
private class ColorBox extends JLabel {
private int color;
public void setColor(int color) {
this.color = color;
repaint();
}
public int getColor() {
return color;
}
public void paintComponent(Graphics g) {
g.setColor(new Color(color));
g.fillRect(0, 0, getWidth(), getHeight());
}
}
/**
*
* Switches to the previous palette index.
* Wrap-around is employed if the current index is the first one (0).
*
**/
public void setPreviousPalIndex() {
view.setKeysEnabled(false);
//
int pi = view.getPalIndex();
pi = (pi == 0) ? view.getPalIndexMaximum() : pi-1;
view.mapDrawColorsToPalIndex(pi);
view.setPalIndex(pi);
viewSelected(view);
//
view.setKeysEnabled(true);
}
/**
*
* Switches to the next palette index.
* Wrap-around is employed if the current index is the last one (maximum).
*
**/
public void setNextPalIndex() {
view.setKeysEnabled(false);
//
int pi = view.getPalIndex();
pi = (pi == view.getPalIndexMaximum()) ? 0 : pi+1;
view.mapDrawColorsToPalIndex(pi);
view.setPalIndex(pi);
viewSelected(view);
//
view.setKeysEnabled(true);
}
/**
*
* Swaps the foreground and background colors.
*
**/
public void swapColors() {
int fg = fgColorBox.getColor();
ui.setFGColor(bgColorBox.getColor());
ui.setBGColor(fg);
}
/**
* Gets the number inside the shiftValueField
* @return the shift to perform
*/
public int getShift() {
try {
return Integer.parseInt(shiftValueField.getText());
} catch (NumberFormatException e) {
return 1;
}
}
public void shiftPalette(int shift) {
view.setKeysEnabled(false);
//
TMPalette palette = view.getPalette();
int offset = palette.getOffset();
int size = palette.getSize();
ColorCodec codec = palette.getCodec();
int endianness = palette.getEndianness();
boolean copy = palette.isDirect();
boolean modified = palette.isModified();
// create the palette
byte[] data = view.getFileImage().getContents();
//checks palette bounds
int newOffset = offset+shift;
//System.out.println("Filesize="+view.getFileImage().getSize()+" pixelsize="+codec.getBytesPerPixel()+" newoffset="+newOffset+" palettesize="+size); USEFUL IN CASE I MESSED THE MATH
if (newOffset < 0){
newOffset = 0;
}
else if (newOffset+(codec.getBytesPerPixel()*size)>=view.getFileImage().getSize()) {
newOffset = view.getFileImage().getSize()-(codec.getBytesPerPixel()*size);
}
palette = new TMPalette("ID", data, newOffset, size, codec, endianness, copy, modified);
// set the new palette
view.setPalette(palette);
viewSelected(view);
ui.refreshStatusBar();
//
view.setKeysEnabled(true);
}
/**
* Locks the palette shifting buttons
*/
public void lockShiftButtons() {
leftShiftButton.setEnabled(false);
rightShiftButton.setEnabled(false);
}
/**
* Unlocks the palette shifting buttons
*/
public void unlockShiftButtons() {
leftShiftButton.setEnabled(true);
rightShiftButton.setEnabled(true);
}
}