mirror of
https://github.com/badvision/jace.git
synced 2024-06-02 01:41:30 +00:00
290 lines
10 KiB
Java
290 lines
10 KiB
Java
/*
|
|
* Copyright (C) 2012 Brendan Robert (BLuRry) brendan.robert@gmail.com.
|
|
*
|
|
* This library is free software; you can redistribute it and/or
|
|
* modify it under the terms of the GNU Lesser General Public
|
|
* License as published by the Free Software Foundation; either
|
|
* version 2.1 of the License, or (at your option) any later version.
|
|
*
|
|
* This library 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
|
|
* Lesser General Public License for more details.
|
|
*
|
|
* You should have received a copy of the GNU Lesser General Public
|
|
* License along with this library; if not, write to the Free Software
|
|
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
|
|
* MA 02110-1301 USA
|
|
*/
|
|
package jace.ui;
|
|
|
|
import jace.core.Computer;
|
|
import java.awt.Color;
|
|
import java.awt.Component;
|
|
import java.awt.Font;
|
|
import java.awt.Frame;
|
|
import java.awt.Graphics;
|
|
import java.awt.event.KeyListener;
|
|
import java.awt.event.WindowAdapter;
|
|
import java.awt.event.WindowEvent;
|
|
import java.awt.image.BufferedImage;
|
|
import java.util.HashMap;
|
|
import java.util.HashSet;
|
|
import java.util.List;
|
|
import java.util.Map;
|
|
import java.util.Set;
|
|
import javax.swing.ImageIcon;
|
|
import javax.swing.JFrame;
|
|
import javax.swing.JLabel;
|
|
import javax.swing.JPanel;
|
|
|
|
/**
|
|
* A newer take on the emulator window, providing a layered user interface for
|
|
* on-screen indicator icons. Created on Mar 27, 2010, 6:40:16 PM
|
|
*
|
|
* @author Brendan Robert (BLuRry) brendan.robert@gmail.com
|
|
*/
|
|
public class EmulatorFrame extends AbstractEmulatorFrame {
|
|
|
|
@Override
|
|
public String getShortName() {
|
|
return "frame";
|
|
}
|
|
|
|
@Override
|
|
public DebuggerPanel getDebuggerPanel() {
|
|
return debuggerPanel;
|
|
}
|
|
|
|
@Override
|
|
public Component getScreen() {
|
|
return screen;
|
|
}
|
|
|
|
@Override
|
|
public void resizeVideo() {
|
|
super.resizeVideo();
|
|
layers.setLayer(screen, layers.lowestLayer());
|
|
layers.validate();
|
|
// On some systems (Ubuntu + Gnome 3) the screen layout gets messed up
|
|
// when toggling between fullscreen. This moves the screen back to the
|
|
// top of the window each time so that issue doesn't happen anymore.
|
|
screen.setLocation(screen.getLocation().x, 0);
|
|
}
|
|
public static final long serialVersionUID = -1100;
|
|
Font labelFont;
|
|
|
|
/**
|
|
* Creates new form EmulatorFrame
|
|
*/
|
|
public EmulatorFrame(Computer computer) {
|
|
setComputer(computer);
|
|
initComponents();
|
|
layers.setDoubleBuffered(true);
|
|
screen.setDoubleBuffered(true);
|
|
labelFont = Font.decode("Ubuntu-BOLD-14");
|
|
if (labelFont == null) {
|
|
labelFont = Font.decode("Arial-BOLD-14");
|
|
}
|
|
layers.setBounds(getContentPane().getBounds());
|
|
screen.setBounds(layers.getBounds());
|
|
debuggerPanel.setVisible(false);
|
|
layers.setPosition(screen, 10);
|
|
layers.setPosition(debuggerPanel, 2);
|
|
reconfigure();
|
|
screen.setFocusTraversalKeysEnabled(false);
|
|
}
|
|
|
|
@Override
|
|
public synchronized void addKeyListener(KeyListener l) {
|
|
super.addKeyListener(l);
|
|
layers.addKeyListener(l);
|
|
screen.addKeyListener(l);
|
|
}
|
|
|
|
/**
|
|
* 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.
|
|
*/
|
|
@SuppressWarnings("unchecked")
|
|
// <editor-fold defaultstate="collapsed" desc="Generated Code">//GEN-BEGIN:initComponents
|
|
private void initComponents() {
|
|
|
|
layers = new javax.swing.JLayeredPane();
|
|
screen = new jace.ui.ScreenPanel();
|
|
debuggerPanel = new jace.ui.DebuggerPanel();
|
|
|
|
setDefaultCloseOperation(javax.swing.WindowConstants.EXIT_ON_CLOSE);
|
|
setBackground(new java.awt.Color(0, 0, 0));
|
|
setCursor(new java.awt.Cursor(java.awt.Cursor.DEFAULT_CURSOR));
|
|
|
|
layers.setBackground(new java.awt.Color(0, 0, 64));
|
|
layers.setOpaque(true);
|
|
|
|
javax.swing.GroupLayout screenLayout = new javax.swing.GroupLayout(screen);
|
|
screen.setLayout(screenLayout);
|
|
screenLayout.setHorizontalGroup(
|
|
screenLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
|
|
.addGap(0, 560, Short.MAX_VALUE)
|
|
);
|
|
screenLayout.setVerticalGroup(
|
|
screenLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
|
|
.addGap(0, 520, Short.MAX_VALUE)
|
|
);
|
|
|
|
screen.setBounds(0, 0, 560, 520);
|
|
layers.add(screen, javax.swing.JLayeredPane.DEFAULT_LAYER);
|
|
debuggerPanel.setBounds(460, 0, 100, 492);
|
|
layers.add(debuggerPanel, javax.swing.JLayeredPane.MODAL_LAYER);
|
|
|
|
javax.swing.GroupLayout layout = new javax.swing.GroupLayout(getContentPane());
|
|
getContentPane().setLayout(layout);
|
|
layout.setHorizontalGroup(
|
|
layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
|
|
.addComponent(layers, javax.swing.GroupLayout.DEFAULT_SIZE, 560, Short.MAX_VALUE)
|
|
);
|
|
layout.setVerticalGroup(
|
|
layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
|
|
.addComponent(layers, javax.swing.GroupLayout.DEFAULT_SIZE, 518, Short.MAX_VALUE)
|
|
);
|
|
|
|
pack();
|
|
}// </editor-fold>//GEN-END:initComponents
|
|
|
|
/**
|
|
* @param args the command line arguments
|
|
*/
|
|
public static void main(String args[]) {
|
|
java.awt.EventQueue.invokeLater(() -> {
|
|
new EmulatorFrame(null).setVisible(true);
|
|
});
|
|
}
|
|
// Variables declaration - do not modify//GEN-BEGIN:variables
|
|
public jace.ui.DebuggerPanel debuggerPanel;
|
|
public javax.swing.JLayeredPane layers;
|
|
public jace.ui.ScreenPanel screen;
|
|
// End of variables declaration//GEN-END:variables
|
|
Set<JLabel> previousIndicators = new HashSet<>();
|
|
|
|
@Override
|
|
public void doRedrawIndicators(Set<ImageIcon> ind) {
|
|
synchronized (previousIndicators) {
|
|
previousIndicators.stream().map((l) -> {
|
|
l.setVisible(false);
|
|
return l;
|
|
}).forEach((l) -> {
|
|
layers.remove(l);
|
|
});
|
|
previousIndicators.clear();
|
|
}
|
|
if (ind != null && !ind.isEmpty()) {
|
|
int x = layers.getWidth();
|
|
int y = layers.getHeight();
|
|
for (ImageIcon i : visibleIndicators) {
|
|
JLabel label = createIndicatorIcon(i);
|
|
x -= (i.getIconWidth() + 10);
|
|
layers.add(label);
|
|
layers.setLayer(label, layers.highestLayer());
|
|
label.setBounds(x, y - i.getIconHeight() - 10, i.getIconWidth() + 5, i.getIconHeight() + 5);
|
|
if (x <= 80) {
|
|
x = layers.getWidth();
|
|
y -= 140;
|
|
}
|
|
synchronized (previousIndicators) {
|
|
previousIndicators.add(label);
|
|
}
|
|
label.setVisible(true);
|
|
}
|
|
} else {
|
|
if (computer != null && computer.video != null) {
|
|
computer.video.forceRefresh();
|
|
}
|
|
// This was causing a whole screen flicker -- bad.
|
|
// screen.repaint();
|
|
}
|
|
screen.requestFocusInWindow();
|
|
}
|
|
|
|
@Override
|
|
public void repaintIndicators() {
|
|
synchronized (previousIndicators) {
|
|
if (previousIndicators != null) {
|
|
previousIndicators.stream().forEach((l) -> {
|
|
Graphics g = l.getGraphics();
|
|
if (g != null) {
|
|
l.paint(g);
|
|
}
|
|
});
|
|
}
|
|
}
|
|
}
|
|
Map<ImageIcon, JLabel> indicatorCache = new HashMap<>();
|
|
|
|
private JLabel createIndicatorIcon(ImageIcon i) {
|
|
if (indicatorCache.containsKey(i)) {
|
|
return indicatorCache.get(i);
|
|
}
|
|
JLabel label = new OutlinedLabel(i.getDescription());
|
|
label.setIcon(i);
|
|
label.setHorizontalTextPosition(JLabel.CENTER);
|
|
label.setVerticalTextPosition(JLabel.CENTER);
|
|
label.setBackground(Color.BLACK);
|
|
label.setForeground(Color.WHITE);
|
|
label.setFont(labelFont);
|
|
label.setOpaque(false);
|
|
label.setFocusable(false);
|
|
label.setBounds(0, 0, i.getIconWidth(), i.getIconHeight());
|
|
BufferedImage img = new BufferedImage(i.getIconWidth(), i.getIconHeight(), BufferedImage.TYPE_INT_ARGB);
|
|
label.paint(img.getGraphics());
|
|
ImageIcon icon = new ImageIcon(img);
|
|
JLabel renderedLabel = new JLabel(icon);
|
|
indicatorCache.put(i, renderedLabel);
|
|
return renderedLabel;
|
|
}
|
|
Map<String, JFrame> modals = new HashMap<>();
|
|
|
|
@Override
|
|
protected void displayModalDialog(final String name, JPanel ui, List<String> ancestors) {
|
|
final JFrame modal = modals.get(name);
|
|
if (modal != null) {
|
|
modal.setVisible(true);
|
|
modal.setState(Frame.NORMAL);
|
|
modal.toFront();
|
|
modal.requestFocus();
|
|
return;
|
|
}
|
|
JFrame frame = new JFrame();
|
|
modals.put(name, frame);
|
|
frame.addWindowStateListener(new WindowAdapter() {
|
|
@Override
|
|
public void windowClosing(WindowEvent e) {
|
|
closeDialog(name);
|
|
}
|
|
});
|
|
frame.setDefaultCloseOperation(JFrame.HIDE_ON_CLOSE);
|
|
frame.setTitle(name);
|
|
frame.setContentPane(ui);
|
|
frame.setSize(ui.getPreferredSize());
|
|
frame.validate();
|
|
frame.setVisible(true);
|
|
}
|
|
|
|
@Override
|
|
protected void disposeModalDialog(String name) {
|
|
JFrame modal = modals.get(name);
|
|
if (modal != null) {
|
|
modals.remove(name);
|
|
modal.dispose();
|
|
}
|
|
modals.remove(name);
|
|
}
|
|
|
|
@Override
|
|
protected void hideModalDialog(String name) {
|
|
JFrame modal = modals.get(name);
|
|
if (modal != null) {
|
|
modal.setVisible(false);
|
|
}
|
|
}
|
|
} |