dmolony-DiskBrowser/src/com/bytezone/diskbrowser/gui/DiskLayoutImage.java

329 lines
12 KiB
Java
Raw Normal View History

2015-06-01 09:35:51 +00:00
package com.bytezone.diskbrowser.gui;
2020-02-08 10:13:51 +00:00
import java.awt.Color;
import java.awt.Cursor;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Point;
import java.awt.Rectangle;
2015-06-01 09:35:51 +00:00
import java.awt.event.InputEvent;
import java.awt.event.KeyAdapter;
import java.awt.event.KeyEvent;
2015-06-01 09:35:51 +00:00
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.util.List;
import javax.swing.Scrollable;
import javax.swing.SwingConstants;
import com.bytezone.diskbrowser.disk.Disk;
import com.bytezone.diskbrowser.disk.DiskAddress;
import com.bytezone.diskbrowser.disk.FormattedDisk;
import com.bytezone.diskbrowser.disk.SectorType;
import com.bytezone.diskbrowser.gui.DiskLayoutPanel.LayoutDetails;
import com.bytezone.diskbrowser.gui.RedoHandler.RedoEvent;
2016-03-03 07:04:47 +00:00
import com.bytezone.diskbrowser.gui.RedoHandler.RedoListener;
2015-06-01 09:35:51 +00:00
2020-02-08 10:13:51 +00:00
// -----------------------------------------------------------------------------------//
2018-07-18 05:14:17 +00:00
class DiskLayoutImage extends DiskPanel implements Scrollable, RedoListener
2020-02-08 10:13:51 +00:00
// -----------------------------------------------------------------------------------//
2015-06-01 09:35:51 +00:00
{
2016-07-18 08:55:32 +00:00
private static final Cursor crosshairCursor = new Cursor (Cursor.CROSSHAIR_CURSOR);
private static final Color[] lightColors =
{ Color.WHITE, Color.YELLOW, Color.PINK, Color.CYAN, Color.ORANGE, Color.GREEN };
2016-02-28 05:41:10 +00:00
2015-06-01 09:35:51 +00:00
private boolean showFreeSectors;
private final DiskLayoutSelection selectionHandler = new DiskLayoutSelection ();
private boolean redo;
2015-06-01 09:35:51 +00:00
// set defaults (used until a real disk is set)
2018-07-18 05:14:17 +00:00
private int gridWidth = 8;
private int gridHeight = 35;
2015-06-01 09:35:51 +00:00
2020-02-08 10:13:51 +00:00
// ---------------------------------------------------------------------------------//
2015-06-01 09:35:51 +00:00
public DiskLayoutImage ()
2020-02-08 10:13:51 +00:00
// ---------------------------------------------------------------------------------//
2015-06-01 09:35:51 +00:00
{
setPreferredSize (new Dimension (240 + 1, 525 + 1));
addMouseListener (new MyMouseListener ());
2018-07-18 05:14:17 +00:00
setBackground (backgroundColor);
2018-08-16 00:09:26 +00:00
// setOpaque (true);
// https://stackoverflow.com/questions/2451990/setopaquetrue-false-java
addKeyListener (new MyKeyListener ());
2015-06-01 09:35:51 +00:00
}
2020-02-08 10:13:51 +00:00
// ---------------------------------------------------------------------------------//
2018-07-18 05:14:17 +00:00
@Override
2015-06-01 09:35:51 +00:00
public void setDisk (FormattedDisk disk, LayoutDetails details)
2020-02-08 10:13:51 +00:00
// ---------------------------------------------------------------------------------//
2015-06-01 09:35:51 +00:00
{
2018-07-18 05:14:17 +00:00
super.setDisk (disk, details);
2015-06-01 09:35:51 +00:00
2018-07-18 05:14:17 +00:00
gridWidth = layoutDetails.grid.width; // width in blocks
gridHeight = layoutDetails.grid.height; // height in blocks
2015-06-01 09:35:51 +00:00
2018-07-18 05:14:17 +00:00
setPreferredSize (
new Dimension (gridWidth * blockWidth + 1, gridHeight * blockHeight + 1));
2015-06-01 09:35:51 +00:00
selectionHandler.setSelection (null);
repaint ();
}
2020-02-08 10:13:51 +00:00
// ---------------------------------------------------------------------------------//
2016-02-28 05:41:10 +00:00
public FormattedDisk getDisk ()
2020-02-08 10:13:51 +00:00
// ---------------------------------------------------------------------------------//
2016-02-28 05:41:10 +00:00
{
2018-07-18 05:14:17 +00:00
return formattedDisk;
2016-02-28 05:41:10 +00:00
}
2020-02-08 10:13:51 +00:00
// ---------------------------------------------------------------------------------//
2015-06-01 09:35:51 +00:00
public void setShowFreeSectors (boolean showFree)
2020-02-08 10:13:51 +00:00
// ---------------------------------------------------------------------------------//
2015-06-01 09:35:51 +00:00
{
2018-07-18 05:14:17 +00:00
if (showFree != showFreeSectors)
{
showFreeSectors = showFree;
repaint ();
}
2015-06-01 09:35:51 +00:00
}
2020-02-08 10:13:51 +00:00
// ---------------------------------------------------------------------------------//
2015-06-01 09:35:51 +00:00
void setSelection (List<DiskAddress> sectors)
2020-02-08 10:13:51 +00:00
// ---------------------------------------------------------------------------------//
2015-06-01 09:35:51 +00:00
{
selectionHandler.setSelection (sectors);
if (sectors != null && sectors.size () > 0)
{
DiskAddress da = sectors.size () == 1 ? sectors.get (0) : sectors.get (1);
2018-07-22 20:52:41 +00:00
if (da != null)
scrollRectToVisible (layoutDetails.getLocation (da));
2015-06-01 09:35:51 +00:00
}
repaint ();
}
2020-02-08 10:13:51 +00:00
// ---------------------------------------------------------------------------------//
2015-06-01 09:35:51 +00:00
@Override
protected void paintComponent (Graphics g)
2020-02-08 10:13:51 +00:00
// ---------------------------------------------------------------------------------//
2015-06-01 09:35:51 +00:00
{
super.paintComponent (g);
2018-07-18 05:14:17 +00:00
if (formattedDisk == null)
2015-06-01 09:35:51 +00:00
return;
Rectangle clipRect = g.getClipBounds ();
2018-07-18 05:14:17 +00:00
Point topLeft = new Point (clipRect.x / blockWidth * blockWidth,
clipRect.y / blockHeight * blockHeight);
Point bottomRight =
new Point ((clipRect.x + clipRect.width - 1) / blockWidth * blockWidth,
(clipRect.y + clipRect.height - 1) / blockHeight * blockHeight);
2015-06-01 09:35:51 +00:00
2018-07-18 05:14:17 +00:00
int maxBlock = gridWidth * gridHeight;
Disk d = formattedDisk.getDisk ();
2015-06-01 09:35:51 +00:00
// this stops an index error when using alt-5 to switch to 512-byte blocks
2016-02-28 18:53:59 +00:00
// if (maxBlock > d.getTotalBlocks ())
// maxBlock = d.getTotalBlocks ();
// the index error is caused by not recalculating the grid layout
2015-06-01 09:35:51 +00:00
2018-07-18 05:14:17 +00:00
for (int y = topLeft.y; y <= bottomRight.y; y += blockHeight)
for (int x = topLeft.x; x <= bottomRight.x; x += blockWidth)
2015-06-01 09:35:51 +00:00
{
2018-07-18 05:14:17 +00:00
int blockNo = y / blockHeight * gridWidth + x / blockWidth;
2015-06-01 09:35:51 +00:00
if (blockNo < maxBlock)
{
2018-07-18 05:14:17 +00:00
SectorType type = formattedDisk.getSectorType (blockNo);
if (type == null)
System.out.println ("Sector type is null " + blockNo);
else
{
DiskAddress da = d.getDiskAddress (blockNo);
boolean free = showFreeSectors && formattedDisk.isSectorFree (da);
boolean selected = selectionHandler.isSelected (da);
2019-08-01 07:31:49 +00:00
drawBlock ((Graphics2D) g, type, x, y, free, selected);
2018-07-18 05:14:17 +00:00
}
2015-06-01 09:35:51 +00:00
}
}
}
2020-02-08 10:13:51 +00:00
// ---------------------------------------------------------------------------------//
2018-07-18 05:14:17 +00:00
private void drawBlock (Graphics2D g, SectorType type, int x, int y, boolean flagFree,
2019-08-01 07:31:49 +00:00
boolean selected)
2020-02-08 10:13:51 +00:00
// ---------------------------------------------------------------------------------//
2015-06-01 09:35:51 +00:00
{
2018-06-30 09:40:38 +00:00
g.setColor (type.colour);
2018-08-16 00:09:26 +00:00
g.fillRect (x + 1, y + 1, blockWidth - 1, blockHeight - 1);
2015-06-01 09:35:51 +00:00
2018-07-18 05:14:17 +00:00
if (flagFree || selected)
2015-06-01 09:35:51 +00:00
{
g.setColor (getContrastColor (type));
2018-07-18 05:14:17 +00:00
if (flagFree)
g.drawOval (x + centerOffset - 2, y + 4, 7, 7);
if (selected)
g.fillOval (x + centerOffset, y + 6, 3, 3);
2015-06-01 09:35:51 +00:00
}
}
2020-02-08 10:13:51 +00:00
// ---------------------------------------------------------------------------------//
2015-06-01 09:35:51 +00:00
private Color getContrastColor (SectorType type)
2020-02-08 10:13:51 +00:00
// ---------------------------------------------------------------------------------//
2015-06-01 09:35:51 +00:00
{
2016-07-18 08:55:32 +00:00
for (Color color : lightColors)
if (type.colour == color)
return Color.BLACK;
2015-06-01 09:35:51 +00:00
return Color.WHITE;
}
2020-02-08 10:13:51 +00:00
// ---------------------------------------------------------------------------------//
2015-06-01 09:35:51 +00:00
@Override
public Dimension getPreferredScrollableViewportSize ()
2020-02-08 10:13:51 +00:00
// ---------------------------------------------------------------------------------//
2015-06-01 09:35:51 +00:00
{
2019-07-31 00:01:49 +00:00
return new Dimension (240 + 1, 525 + 1); // floppy disk size
2015-06-01 09:35:51 +00:00
}
2020-02-08 10:13:51 +00:00
// ---------------------------------------------------------------------------------//
2015-06-01 09:35:51 +00:00
@Override
2015-06-02 01:35:49 +00:00
public int getScrollableUnitIncrement (Rectangle visibleRect, int orientation,
int direction)
2020-02-08 10:13:51 +00:00
// ---------------------------------------------------------------------------------//
2015-06-01 09:35:51 +00:00
{
2018-07-18 05:14:17 +00:00
return orientation == SwingConstants.HORIZONTAL ? blockWidth : blockHeight;
2015-06-01 09:35:51 +00:00
}
2020-02-08 10:13:51 +00:00
// ---------------------------------------------------------------------------------//
2015-06-01 09:35:51 +00:00
@Override
2015-06-02 01:35:49 +00:00
public int getScrollableBlockIncrement (Rectangle visibleRect, int orientation,
int direction)
2020-02-08 10:13:51 +00:00
// ---------------------------------------------------------------------------------//
2015-06-01 09:35:51 +00:00
{
2018-07-18 05:14:17 +00:00
return orientation == SwingConstants.HORIZONTAL ? blockWidth * 4 : blockHeight * 10;
2015-06-01 09:35:51 +00:00
}
2020-02-08 10:13:51 +00:00
// ---------------------------------------------------------------------------------//
2015-06-01 09:35:51 +00:00
@Override
public boolean getScrollableTracksViewportHeight ()
2020-02-08 10:13:51 +00:00
// ---------------------------------------------------------------------------------//
2015-06-01 09:35:51 +00:00
{
return false;
}
2020-02-08 10:13:51 +00:00
// ---------------------------------------------------------------------------------//
2015-06-01 09:35:51 +00:00
@Override
public boolean getScrollableTracksViewportWidth ()
2020-02-08 10:13:51 +00:00
// ---------------------------------------------------------------------------------//
2015-06-01 09:35:51 +00:00
{
return false;
}
2020-02-08 10:13:51 +00:00
// ---------------------------------------------------------------------------------//
2016-03-03 07:04:47 +00:00
@Override
public void redo (RedoEvent redoEvent)
2020-02-08 10:13:51 +00:00
// ---------------------------------------------------------------------------------//
2015-06-01 09:35:51 +00:00
{
redo = true;
SectorSelectedEvent event = (SectorSelectedEvent) redoEvent.value;
setSelection (event.getSectors ());
fireSectorSelectionEvent (event);
redo = false;
2016-03-01 08:51:15 +00:00
requestFocusInWindow ();
2015-06-01 09:35:51 +00:00
}
2020-02-08 10:13:51 +00:00
// ---------------------------------------------------------------------------------//
2015-06-01 09:35:51 +00:00
private void fireSectorSelectionEvent ()
2020-02-08 10:13:51 +00:00
// ---------------------------------------------------------------------------------//
2015-06-01 09:35:51 +00:00
{
SectorSelectedEvent event =
2018-07-18 05:14:17 +00:00
new SectorSelectedEvent (this, selectionHandler.getHighlights (), formattedDisk);
2015-06-01 09:35:51 +00:00
fireSectorSelectionEvent (event);
}
2020-02-08 10:13:51 +00:00
// ---------------------------------------------------------------------------------//
2015-06-01 09:35:51 +00:00
private void fireSectorSelectionEvent (SectorSelectedEvent event)
2020-02-08 10:13:51 +00:00
// ---------------------------------------------------------------------------------//
2015-06-01 09:35:51 +00:00
{
event.redo = redo;
SectorSelectionListener[] listeners =
2015-06-02 01:35:49 +00:00
(listenerList.getListeners (SectorSelectionListener.class));
2015-06-01 09:35:51 +00:00
for (SectorSelectionListener listener : listeners)
listener.sectorSelected (event);
}
2020-02-08 10:13:51 +00:00
// ---------------------------------------------------------------------------------//
2015-06-01 09:35:51 +00:00
public void addSectorSelectionListener (SectorSelectionListener listener)
2020-02-08 10:13:51 +00:00
// ---------------------------------------------------------------------------------//
2015-06-01 09:35:51 +00:00
{
listenerList.add (SectorSelectionListener.class, listener);
}
2020-02-08 10:13:51 +00:00
// ---------------------------------------------------------------------------------//
2015-06-01 09:35:51 +00:00
public void removeSectorSelectionListener (SectorSelectionListener listener)
2020-02-08 10:13:51 +00:00
// ---------------------------------------------------------------------------------//
2015-06-01 09:35:51 +00:00
{
listenerList.remove (SectorSelectionListener.class, listener);
}
2020-02-08 10:13:51 +00:00
// ---------------------------------------------------------------------------------//
class MyKeyListener extends KeyAdapter
2020-02-08 10:13:51 +00:00
// ---------------------------------------------------------------------------------//
{
@Override
public void keyPressed (KeyEvent e)
{
switch (e.getKeyCode ())
{
case KeyEvent.VK_LEFT:
case KeyEvent.VK_RIGHT:
case KeyEvent.VK_UP:
case KeyEvent.VK_DOWN:
2018-07-18 05:14:17 +00:00
selectionHandler.cursorMove (formattedDisk, e);
fireSectorSelectionEvent ();
repaint ();
}
}
}
2020-02-08 10:13:51 +00:00
// ---------------------------------------------------------------------------------//
2015-06-01 09:35:51 +00:00
class MyMouseListener extends MouseAdapter
2020-02-08 10:13:51 +00:00
// ---------------------------------------------------------------------------------//
2015-06-01 09:35:51 +00:00
{
private Cursor currentCursor;
@Override
public void mouseClicked (MouseEvent e)
{
2018-07-18 05:14:17 +00:00
int x = e.getX () / blockWidth;
int y = e.getY () / blockHeight;
int blockNo = y * gridWidth + x;
DiskAddress da = formattedDisk.getDisk ().getDiskAddress (blockNo);
2015-06-01 09:35:51 +00:00
boolean extend = ((e.getModifiersEx () & InputEvent.SHIFT_DOWN_MASK) > 0);
boolean append = ((e.getModifiersEx () & InputEvent.CTRL_DOWN_MASK) > 0);
2018-07-18 05:14:17 +00:00
selectionHandler.doClick (formattedDisk.getDisk (), da, extend, append);
2015-06-01 09:35:51 +00:00
fireSectorSelectionEvent ();
repaint ();
requestFocusInWindow ();
2015-06-01 09:35:51 +00:00
}
@Override
public void mouseEntered (MouseEvent e)
{
currentCursor = getCursor ();
setCursor (crosshairCursor);
}
@Override
public void mouseExited (MouseEvent e)
{
setCursor (currentCursor);
}
}
}