455 lines
No EOL
13 KiB
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);
|
|
}
|
|
|
|
} |