The previous and initial iteration at Simulating a GUI windowing systemSimulating a GUI windowing system
The previous and initial iteration at Simulating a GUI windowing system
The previous and initial iteration at Simulating a GUI windowing system
MyCanvas.java: package net.coderodde.gui.simulation;
package net.coderodde.gui.simulation;
import java.awt.Canvas;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import java.awt.event.MouseMotionListener;
import java.util.List;
class MyCanvas extends Canvas {
private final int width;
private final int height;
private final List<MyWindow> windowList;
MyCanvas(final int width,
final int height,
final List<MyWindow> wndList,
final MyScreen screen) {
this.width = width;
this.height = height;
setSize(width, height);
this.windowList = wndList;
final MyMouseListener mml = new MyMouseListener(screen);
addMouseListener(mml);
addMouseMotionListener(mml);
}
@Override
public void paint(final Graphics g) {
g.setColor(Color.BLACK);
g.fillRect(0, 0, width, height);
for (final MyWindow wnd : windowList) {
wnd.draw(g);
}
}
@Override
public void update(final Graphics g) {
paint(g);
}
@Override
public Dimension getPreferredSize() {
return new Dimension(width, height);
}
static class MyMouseListener implements MouseListener,
MouseMotionListener {
private final MyScreen screen;
MyMouseListener(final MyScreen screen) {
this.screen = screen;
}
@Override
public void mouseClicked(MouseEvent e) {
}
@Override
public void mousePressed(MouseEvent e) {
screen.press(e.getX(), e.getY());
}
@Override
public void mouseReleased(MouseEvent e) {
screen.releaseMouse();
}
@Override
public void mouseEntered(MouseEvent e) {
screen.allowDrag();
}
@Override
public void mouseExited(MouseEvent e) {
screen.disallowDrag();
}
@Override
public void mouseDragged(MouseEvent e) {
screen.drag(e.getX(), e.getY());
}
@Override
public void mouseMoved(MouseEvent e) {
screen.move(e.getX(), e.getY());
}
}
}
MyScreen: package net.coderodde.gui.simulation;
package net.coderodde.gui.simulation;
import java.awt.Canvas;
import java.awt.Dimension;
import java.util.List;
import java.awt.Toolkit;
import java.util.ArrayList;
import javax.swing.JFrame;
public class MyScreen {
private final static int FRAME_WIDTH = 1024;
private final static int FRAME_HEIGHT = 768;
private final JFrame frame;
private final Canvas canvas;
private final List<MyWindow> windowList;
private MyWindow activeWindow;
private MyWindow draggedWindow;
private int draggedWindowOffsetX;
private int draggedWindowOffsetY;
private boolean topBorderLocked;
private boolean rightBorderLocked;
private boolean bottomBorderLocked;
private boolean leftBorderLocked;
private MyWindow highlightedWindow;
private boolean disallowDrag;
public MyScreen() {
windowList = new ArrayList<>();
frame = new JFrame("coderodde GUI simulation");
frame.setSize(FRAME_WIDTH, FRAME_HEIGHT);
frame.setResizable(false);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
final Dimension realScreenDimension =
Toolkit.getDefaultToolkit().getScreenSize();
frame.setLocation((realScreenDimension.width - frame.getWidth()) / 2,
(realScreenDimension.height - frame.getHeight()) / 2);
canvas = new MyCanvas(frame.getWidth(),
frame.getHeight(),
windowList,
this);
frame.add(canvas);
frame.setVisible(true);
}
public void addWindow(final MyWindow window) {
windowList.add(window);
if (activeWindow != null) {
activeWindow.setActive(false);
}
window.setActive(true);
activeWindow = window;
}
public void move(final int x, final int y) {
MyWindow target = null;
for (int i = windowList.size() - 1; i >= 0; --i) {
if (windowList.get(i).windowContainsPoint(x, y)) {
target = windowList.get(i);
break;
}
}
if (target == null) {
if (highlightedWindow != null) {
highlightedWindow.clearBorderHighlights();
highlightedWindow = null;
canvas.repaint();
}
return;
}
if (highlightedWindow != null) {
highlightedWindow.clearBorderHighlights();
highlightedWindow = null;
}
if (target.topBorderContainsPoint(x, y)) {
target.highlightBorder(MyWindow.Border.TOP);
highlightedWindow = target;
} else if (target.bottomBorderContainsPoint(x, y)) {
target.highlightBorder(MyWindow.Border.BOTTOM);
highlightedWindow = target;
}
if (target.rightBorderContainsPoint(x, y)) {
target.highlightBorder(MyWindow.Border.RIGHT);
highlightedWindow = target;
} else if (target.leftBorderContainsPoint(x, y)) {
target.highlightBorder(MyWindow.Border.LEFT);
highlightedWindow = target;
}
canvas.repaint();
}
public void press(final int x, final int y) {
MyWindow newActiveWindow = null;
for (int i = windowList.size() - 1; i >= 0; --i) {
if (windowList.get(i).windowContainsPoint(x, y)) {
newActiveWindow = windowList.remove(i);
break;
}
}
if (newActiveWindow == null) {
return;
}
activeWindow.setActive(false);
activeWindow = newActiveWindow;
windowList.add(activeWindow);
activeWindow.setActive(true);
boolean doResize = false;
if (activeWindow.topBorderContainsPoint(x, y)) {
topBorderLocked = true;
doResize = true;
} else if (activeWindow.bottomBorderContainsPoint(x, y)) {
bottomBorderLocked = true;
doResize = true;
}
if (activeWindow.leftBorderContainsPoint(x, y)) {
leftBorderLocked = true;
doResize = true;
} else if (activeWindow.rightBorderContainsPoint(x, y)) {
rightBorderLocked = true;
doResize = true;
}
if (!doResize && activeWindow.titleBarContainsPoint(x, y)) {
draggedWindow = activeWindow;
draggedWindowOffsetX = x - draggedWindow.getX();
draggedWindowOffsetY = y - draggedWindow.getY();
}
if (doResize) {
draggedWindow = activeWindow;
}
canvas.repaint();
}
public void allowDrag() {
disallowDrag = false;
}
public void disallowDrag() {
disallowDrag = true;
}
public void drag(final int x, final int y) {
if (draggedWindow == null) {
return;
}
if (disallowDrag) {
return;
}
if (!(topBorderLocked
|| rightBorderLocked
|| bottomBorderLocked
|| leftBorderLocked)) {
// Move the entire window.
draggedWindow.setX(x - draggedWindowOffsetX);
draggedWindow.setY(y - draggedWindowOffsetY);
canvas.repaint();
}
// Resize the window.
final int originalX = draggedWindow.getX();
final int originalY = draggedWindow.getY();
if (topBorderLocked) {
draggedWindow.resizeAtTop(y - originalY);
} else if (bottomBorderLocked) {
draggedWindow.setHeight(y - originalY);
}
if (leftBorderLocked) {
draggedWindow.resizeAtLeft(x - originalX);
} else if (rightBorderLocked) {
draggedWindow.setWidth(x - originalX);
}
canvas.repaint();
}
public void releaseMouse() {
draggedWindow = null;
topBorderLocked = false;
leftBorderLocked = false;
bottomBorderLocked = false;
rightBorderLocked = false;
}
List<MyWindow> getWindows() {
return windowList;
}
}
MyWindow.java: package net.coderodde.gui.simulation;
package net.coderodde.gui.simulation;
import java.awt.Color;
import java.awt.Font;
import java.awt.FontMetrics;
import java.awt.Graphics;
public class MyWindow {
public static enum Border {
TOP,
RIGHT,
BOTTOM,
LEFT
}
public final static int MINIMUM_WIDTH = 50;
public final static int MINIMUM_HEIGHT = 50;
private final static int TITLE_BAR_HEIGHT = 30;
private final static Color ACTIVE_TITLE_BAR_BACKGROUND = new Color(255, 150, 100);
private final static Color TITLE_BAR_TEXT_COLOR = Color.WHITE;
private final static Color PASSIVE_TITLE_BAR_BACKGROUND = new Color(200, 200, 200);
private final static Color BORDER_HIGHLIGHT_COLOR = Color.GREEN;
private final static Color BODY_COLOR = new Color(50, 50, 50);
private final static Font TITLE_FONT = new Font("Monospaced", Font.BOLD, 12);
private final static int TITLE_PADDING = 14;
private String title;
private int width;
private int height;
private int x;
private int y;
private boolean active;
private boolean topBorderHightlighted;
private boolean rightBorderHighlighted;
private boolean bottomBorderHightlighted;
private boolean leftBorderHighlighted;
private boolean debug;
public MyWindow(final String title,
final int width,
final int height,
final int x,
final int y) {
this.title = title;
this.width = Math.max(width, MINIMUM_WIDTH);
this.height = Math.max(height, MINIMUM_HEIGHT) + TITLE_BAR_HEIGHT;
this.x = x;
this.y = y;
this.active = false;
}
public void setDebug(final boolean debug) {
this.debug = debug;
}
public boolean isActive() {
return active;
}
public void setActive(final boolean active) {
this.active = active;
}
public void clearBorderHighlights() {
topBorderHightlighted = false;
rightBorderHighlighted = false;
bottomBorderHightlighted = false;
leftBorderHighlighted = false;
}
public void highlightBorder(Border border) {
switch (border) {
case TOP:
topBorderHightlighted = true;
return;
case RIGHT:
rightBorderHighlighted = true;
return;
case BOTTOM:
bottomBorderHightlighted = true;
return;
case LEFT:
leftBorderHighlighted = true;
return;
}
}
public String getTitle() {
return title;
}
public void setTitle(final String title) {
this.title = title;
}
public int getWidth() {
return width;
}
public void setWidth(final int width) {
this.width = Math.max(width, MINIMUM_WIDTH);
}
public int getHeight() {
return height;
}
public void setHeight(final int height) {
if (debug) {
System.out.println("Height changed from " + getHeight() + " to " +
height);
}
this.height = Math.max(height, MINIMUM_HEIGHT);
}
public int getX() {
return x;
}
public int getY() {
return y;
}
public void setX(final int x) {
this.x = x;
}
public void setY(final int y) {
this.y = y;
}
public boolean titleBarContainsPoint(final int x, final int y) {
return getX() <= x
&& x < getX() + width
&& getY() <= y
&& y < getY() + TITLE_BAR_HEIGHT;
}
public boolean windowContainsPoint(final int x, final int y) {
return getX() <= x
&& x < getX() + width
&& getY() <= y
&& y < getY() + height;
}
public boolean topBorderContainsPoint(final int x, final int y) {
return getX() <= x
&& x < getX() + width
&& (y == getY() || y == getY() + 1);
}
public boolean rightBorderContainsPoint(final int x, final int y) {
return (x == getX() + width - 1 || x == getX() + width - 2)
&& getY() <= y
&& y < getY() + height;
}
public boolean bottomBorderContainsPoint(final int xx, final int yy) {
return getX() <= xx
&& xx < getX() + width
&& (yy == getY() + height - 1 || yy == getY() + height - 2);
}
public boolean leftBorderContainsPoint(final int x, final int y) {
return (x == getX() || x == getX() + 1)
&& getY() <= y
&& y < getY() + height;
}
public void draw(final Graphics g) {
final Color titleBarColor = isActive() ?
ACTIVE_TITLE_BAR_BACKGROUND :
PASSIVE_TITLE_BAR_BACKGROUND;
// Draw title bar.
g.setColor(titleBarColor);
g.fillRect(x, y, width, TITLE_BAR_HEIGHT);
g.setColor(TITLE_BAR_TEXT_COLOR);
g.setFont(TITLE_FONT);
g.drawString(getContractedTitle(g.getFontMetrics(TITLE_FONT)),
x + TITLE_PADDING,
y + 18);
// Fill body rectangle.
g.setColor(BODY_COLOR);
g.fillRect(x, y + TITLE_BAR_HEIGHT, width, height - TITLE_BAR_HEIGHT);
// Draw left, right and bottom colors.
g.setColor(titleBarColor);
// Draw left border.
g.drawLine(x, y, x, y + height - 1);
// Draw right border.
g.drawLine(x + width - 1, y, x + width - 1, y + height - 1);
// Draw bottom border
g.drawLine(x, y + height - 1, x + width - 1, y + height - 1);
// Try draw border highlights.
g.setColor(BORDER_HIGHLIGHT_COLOR);
// Top border.
if (topBorderHightlighted) {
g.fillRect(x, y, width, 2);
}
// Left border.
if (leftBorderHighlighted) {
g.fillRect(x, y, 2, height);
}
// Right border.
if (rightBorderHighlighted) {
g.fillRect(x + width - 2, y, 2, height);
}
// Bottom border.
if (bottomBorderHightlighted) {
g.fillRect(x, y + height - 2, width, 2);
}
}
public void resizeAtTop(final int delta) {
final int oldHeight = height;
height = Math.max(MINIMUM_HEIGHT, height - delta);
y += (oldHeight - height);
}
public void resizeAtLeft(final int delta) {
final int oldWidth = width;
width = Math.max(MINIMUM_WIDTH, width - delta);
x += (oldWidth - width);
}
private String getContractedTitle(final FontMetrics fm) {
final int allowedWidth = getWidth() - 2 * TITLE_PADDING;
if (fm.stringWidth(title) <= allowedWidth) {
// Once here, the window title fits entirely in the title bar.
return title;
}
// Once here, we need to contract the string from right.
for (int i = title.length() - 1; i > 0; --i) {
final String contractedTitle = title.substring(0, i);
final String titleWithDots = contractedTitle + "...";
if (fm.stringWidth(titleWithDots) <= allowedWidth) {
return titleWithDots;
}
}
if (fm.stringWidth("...") <= allowedWidth) {
return "...";
}
if (fm.stringWidth("..") <= allowedWidth) {
return "..";
}
return "";
}
}
MyCanvas.java: package net.coderodde.gui.simulation;
import java.awt.Canvas;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import java.awt.event.MouseMotionListener;
import java.util.List;
class MyCanvas extends Canvas {
private final int width;
private final int height;
private final List<MyWindow> windowList;
MyCanvas(final int width,
final int height,
final List<MyWindow> wndList,
final MyScreen screen) {
this.width = width;
this.height = height;
setSize(width, height);
this.windowList = wndList;
final MyMouseListener mml = new MyMouseListener(screen);
addMouseListener(mml);
addMouseMotionListener(mml);
}
@Override
public void paint(final Graphics g) {
g.setColor(Color.BLACK);
g.fillRect(0, 0, width, height);
for (final MyWindow wnd : windowList) {
wnd.draw(g);
}
}
@Override
public void update(final Graphics g) {
paint(g);
}
@Override
public Dimension getPreferredSize() {
return new Dimension(width, height);
}
static class MyMouseListener implements MouseListener,
MouseMotionListener {
private final MyScreen screen;
MyMouseListener(final MyScreen screen) {
this.screen = screen;
}
@Override
public void mouseClicked(MouseEvent e) {
}
@Override
public void mousePressed(MouseEvent e) {
screen.press(e.getX(), e.getY());
}
@Override
public void mouseReleased(MouseEvent e) {
screen.releaseMouse();
}
@Override
public void mouseEntered(MouseEvent e) {
screen.allowDrag();
}
@Override
public void mouseExited(MouseEvent e) {
screen.disallowDrag();
}
@Override
public void mouseDragged(MouseEvent e) {
screen.drag(e.getX(), e.getY());
}
@Override
public void mouseMoved(MouseEvent e) {
screen.move(e.getX(), e.getY());
}
}
}
MyScreen: package net.coderodde.gui.simulation;
import java.awt.Canvas;
import java.awt.Dimension;
import java.util.List;
import java.awt.Toolkit;
import java.util.ArrayList;
import javax.swing.JFrame;
public class MyScreen {
private final static int FRAME_WIDTH = 1024;
private final static int FRAME_HEIGHT = 768;
private final JFrame frame;
private final Canvas canvas;
private final List<MyWindow> windowList;
private MyWindow activeWindow;
private MyWindow draggedWindow;
private int draggedWindowOffsetX;
private int draggedWindowOffsetY;
private boolean topBorderLocked;
private boolean rightBorderLocked;
private boolean bottomBorderLocked;
private boolean leftBorderLocked;
private MyWindow highlightedWindow;
private boolean disallowDrag;
public MyScreen() {
windowList = new ArrayList<>();
frame = new JFrame("coderodde GUI simulation");
frame.setSize(FRAME_WIDTH, FRAME_HEIGHT);
frame.setResizable(false);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
final Dimension realScreenDimension =
Toolkit.getDefaultToolkit().getScreenSize();
frame.setLocation((realScreenDimension.width - frame.getWidth()) / 2,
(realScreenDimension.height - frame.getHeight()) / 2);
canvas = new MyCanvas(frame.getWidth(),
frame.getHeight(),
windowList,
this);
frame.add(canvas);
frame.setVisible(true);
}
public void addWindow(final MyWindow window) {
windowList.add(window);
if (activeWindow != null) {
activeWindow.setActive(false);
}
window.setActive(true);
activeWindow = window;
}
public void move(final int x, final int y) {
MyWindow target = null;
for (int i = windowList.size() - 1; i >= 0; --i) {
if (windowList.get(i).windowContainsPoint(x, y)) {
target = windowList.get(i);
break;
}
}
if (target == null) {
if (highlightedWindow != null) {
highlightedWindow.clearBorderHighlights();
highlightedWindow = null;
canvas.repaint();
}
return;
}
if (highlightedWindow != null) {
highlightedWindow.clearBorderHighlights();
highlightedWindow = null;
}
if (target.topBorderContainsPoint(x, y)) {
target.highlightBorder(MyWindow.Border.TOP);
highlightedWindow = target;
} else if (target.bottomBorderContainsPoint(x, y)) {
target.highlightBorder(MyWindow.Border.BOTTOM);
highlightedWindow = target;
}
if (target.rightBorderContainsPoint(x, y)) {
target.highlightBorder(MyWindow.Border.RIGHT);
highlightedWindow = target;
} else if (target.leftBorderContainsPoint(x, y)) {
target.highlightBorder(MyWindow.Border.LEFT);
highlightedWindow = target;
}
canvas.repaint();
}
public void press(final int x, final int y) {
MyWindow newActiveWindow = null;
for (int i = windowList.size() - 1; i >= 0; --i) {
if (windowList.get(i).windowContainsPoint(x, y)) {
newActiveWindow = windowList.remove(i);
break;
}
}
if (newActiveWindow == null) {
return;
}
activeWindow.setActive(false);
activeWindow = newActiveWindow;
windowList.add(activeWindow);
activeWindow.setActive(true);
boolean doResize = false;
if (activeWindow.topBorderContainsPoint(x, y)) {
topBorderLocked = true;
doResize = true;
} else if (activeWindow.bottomBorderContainsPoint(x, y)) {
bottomBorderLocked = true;
doResize = true;
}
if (activeWindow.leftBorderContainsPoint(x, y)) {
leftBorderLocked = true;
doResize = true;
} else if (activeWindow.rightBorderContainsPoint(x, y)) {
rightBorderLocked = true;
doResize = true;
}
if (!doResize && activeWindow.titleBarContainsPoint(x, y)) {
draggedWindow = activeWindow;
draggedWindowOffsetX = x - draggedWindow.getX();
draggedWindowOffsetY = y - draggedWindow.getY();
}
if (doResize) {
draggedWindow = activeWindow;
}
canvas.repaint();
}
public void allowDrag() {
disallowDrag = false;
}
public void disallowDrag() {
disallowDrag = true;
}
public void drag(final int x, final int y) {
if (draggedWindow == null) {
return;
}
if (disallowDrag) {
return;
}
if (!(topBorderLocked
|| rightBorderLocked
|| bottomBorderLocked
|| leftBorderLocked)) {
// Move the entire window.
draggedWindow.setX(x - draggedWindowOffsetX);
draggedWindow.setY(y - draggedWindowOffsetY);
canvas.repaint();
}
// Resize the window.
final int originalX = draggedWindow.getX();
final int originalY = draggedWindow.getY();
if (topBorderLocked) {
draggedWindow.resizeAtTop(y - originalY);
} else if (bottomBorderLocked) {
draggedWindow.setHeight(y - originalY);
}
if (leftBorderLocked) {
draggedWindow.resizeAtLeft(x - originalX);
} else if (rightBorderLocked) {
draggedWindow.setWidth(x - originalX);
}
canvas.repaint();
}
public void releaseMouse() {
draggedWindow = null;
topBorderLocked = false;
leftBorderLocked = false;
bottomBorderLocked = false;
rightBorderLocked = false;
}
List<MyWindow> getWindows() {
return windowList;
}
}
MyWindow.java: package net.coderodde.gui.simulation;
import java.awt.Color;
import java.awt.Font;
import java.awt.FontMetrics;
import java.awt.Graphics;
public class MyWindow {
public static enum Border {
TOP,
RIGHT,
BOTTOM,
LEFT
}
public final static int MINIMUM_WIDTH = 50;
public final static int MINIMUM_HEIGHT = 50;
private final static int TITLE_BAR_HEIGHT = 30;
private final static Color ACTIVE_TITLE_BAR_BACKGROUND = new Color(255, 150, 100);
private final static Color TITLE_BAR_TEXT_COLOR = Color.WHITE;
private final static Color PASSIVE_TITLE_BAR_BACKGROUND = new Color(200, 200, 200);
private final static Color BORDER_HIGHLIGHT_COLOR = Color.GREEN;
private final static Color BODY_COLOR = new Color(50, 50, 50);
private final static Font TITLE_FONT = new Font("Monospaced", Font.BOLD, 12);
private final static int TITLE_PADDING = 14;
private String title;
private int width;
private int height;
private int x;
private int y;
private boolean active;
private boolean topBorderHightlighted;
private boolean rightBorderHighlighted;
private boolean bottomBorderHightlighted;
private boolean leftBorderHighlighted;
private boolean debug;
public MyWindow(final String title,
final int width,
final int height,
final int x,
final int y) {
this.title = title;
this.width = Math.max(width, MINIMUM_WIDTH);
this.height = Math.max(height, MINIMUM_HEIGHT) + TITLE_BAR_HEIGHT;
this.x = x;
this.y = y;
this.active = false;
}
public void setDebug(final boolean debug) {
this.debug = debug;
}
public boolean isActive() {
return active;
}
public void setActive(final boolean active) {
this.active = active;
}
public void clearBorderHighlights() {
topBorderHightlighted = false;
rightBorderHighlighted = false;
bottomBorderHightlighted = false;
leftBorderHighlighted = false;
}
public void highlightBorder(Border border) {
switch (border) {
case TOP:
topBorderHightlighted = true;
return;
case RIGHT:
rightBorderHighlighted = true;
return;
case BOTTOM:
bottomBorderHightlighted = true;
return;
case LEFT:
leftBorderHighlighted = true;
return;
}
}
public String getTitle() {
return title;
}
public void setTitle(final String title) {
this.title = title;
}
public int getWidth() {
return width;
}
public void setWidth(final int width) {
this.width = Math.max(width, MINIMUM_WIDTH);
}
public int getHeight() {
return height;
}
public void setHeight(final int height) {
if (debug) {
System.out.println("Height changed from " + getHeight() + " to " +
height);
}
this.height = Math.max(height, MINIMUM_HEIGHT);
}
public int getX() {
return x;
}
public int getY() {
return y;
}
public void setX(final int x) {
this.x = x;
}
public void setY(final int y) {
this.y = y;
}
public boolean titleBarContainsPoint(final int x, final int y) {
return getX() <= x
&& x < getX() + width
&& getY() <= y
&& y < getY() + TITLE_BAR_HEIGHT;
}
public boolean windowContainsPoint(final int x, final int y) {
return getX() <= x
&& x < getX() + width
&& getY() <= y
&& y < getY() + height;
}
public boolean topBorderContainsPoint(final int x, final int y) {
return getX() <= x
&& x < getX() + width
&& (y == getY() || y == getY() + 1);
}
public boolean rightBorderContainsPoint(final int x, final int y) {
return (x == getX() + width - 1 || x == getX() + width - 2)
&& getY() <= y
&& y < getY() + height;
}
public boolean bottomBorderContainsPoint(final int xx, final int yy) {
return getX() <= xx
&& xx < getX() + width
&& (yy == getY() + height - 1 || yy == getY() + height - 2);
}
public boolean leftBorderContainsPoint(final int x, final int y) {
return (x == getX() || x == getX() + 1)
&& getY() <= y
&& y < getY() + height;
}
public void draw(final Graphics g) {
final Color titleBarColor = isActive() ?
ACTIVE_TITLE_BAR_BACKGROUND :
PASSIVE_TITLE_BAR_BACKGROUND;
// Draw title bar.
g.setColor(titleBarColor);
g.fillRect(x, y, width, TITLE_BAR_HEIGHT);
g.setColor(TITLE_BAR_TEXT_COLOR);
g.setFont(TITLE_FONT);
g.drawString(getContractedTitle(g.getFontMetrics(TITLE_FONT)),
x + TITLE_PADDING,
y + 18);
// Fill body rectangle.
g.setColor(BODY_COLOR);
g.fillRect(x, y + TITLE_BAR_HEIGHT, width, height - TITLE_BAR_HEIGHT);
// Draw left, right and bottom colors.
g.setColor(titleBarColor);
// Draw left border.
g.drawLine(x, y, x, y + height - 1);
// Draw right border.
g.drawLine(x + width - 1, y, x + width - 1, y + height - 1);
// Draw bottom border
g.drawLine(x, y + height - 1, x + width - 1, y + height - 1);
// Try draw border highlights.
g.setColor(BORDER_HIGHLIGHT_COLOR);
// Top border.
if (topBorderHightlighted) {
g.fillRect(x, y, width, 2);
}
// Left border.
if (leftBorderHighlighted) {
g.fillRect(x, y, 2, height);
}
// Right border.
if (rightBorderHighlighted) {
g.fillRect(x + width - 2, y, 2, height);
}
// Bottom border.
if (bottomBorderHightlighted) {
g.fillRect(x, y + height - 2, width, 2);
}
}
public void resizeAtTop(final int delta) {
final int oldHeight = height;
height = Math.max(MINIMUM_HEIGHT, height - delta);
y += (oldHeight - height);
}
public void resizeAtLeft(final int delta) {
final int oldWidth = width;
width = Math.max(MINIMUM_WIDTH, width - delta);
x += (oldWidth - width);
}
private String getContractedTitle(final FontMetrics fm) {
final int allowedWidth = getWidth() - 2 * TITLE_PADDING;
if (fm.stringWidth(title) <= allowedWidth) {
// Once here, the window title fits entirely in the title bar.
return title;
}
// Once here, we need to contract the string from right.
for (int i = title.length() - 1; i > 0; --i) {
final String contractedTitle = title.substring(0, i);
final String titleWithDots = contractedTitle + "...";
if (fm.stringWidth(titleWithDots) <= allowedWidth) {
return titleWithDots;
}
}
if (fm.stringWidth("...") <= allowedWidth) {
return "...";
}
if (fm.stringWidth("..") <= allowedWidth) {
return "..";
}
return "";
}
}
MyCanvas.java:
package net.coderodde.gui.simulation;
import java.awt.Canvas;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import java.awt.event.MouseMotionListener;
import java.util.List;
class MyCanvas extends Canvas {
private final int width;
private final int height;
private final List<MyWindow> windowList;
MyCanvas(final int width,
final int height,
final List<MyWindow> wndList,
final MyScreen screen) {
this.width = width;
this.height = height;
setSize(width, height);
this.windowList = wndList;
final MyMouseListener mml = new MyMouseListener(screen);
addMouseListener(mml);
addMouseMotionListener(mml);
}
@Override
public void paint(final Graphics g) {
g.setColor(Color.BLACK);
g.fillRect(0, 0, width, height);
for (final MyWindow wnd : windowList) {
wnd.draw(g);
}
}
@Override
public void update(final Graphics g) {
paint(g);
}
@Override
public Dimension getPreferredSize() {
return new Dimension(width, height);
}
static class MyMouseListener implements MouseListener,
MouseMotionListener {
private final MyScreen screen;
MyMouseListener(final MyScreen screen) {
this.screen = screen;
}
@Override
public void mouseClicked(MouseEvent e) {
}
@Override
public void mousePressed(MouseEvent e) {
screen.press(e.getX(), e.getY());
}
@Override
public void mouseReleased(MouseEvent e) {
screen.releaseMouse();
}
@Override
public void mouseEntered(MouseEvent e) {
screen.allowDrag();
}
@Override
public void mouseExited(MouseEvent e) {
screen.disallowDrag();
}
@Override
public void mouseDragged(MouseEvent e) {
screen.drag(e.getX(), e.getY());
}
@Override
public void mouseMoved(MouseEvent e) {
screen.move(e.getX(), e.getY());
}
}
}
MyScreen:
package net.coderodde.gui.simulation;
import java.awt.Canvas;
import java.awt.Dimension;
import java.util.List;
import java.awt.Toolkit;
import java.util.ArrayList;
import javax.swing.JFrame;
public class MyScreen {
private final static int FRAME_WIDTH = 1024;
private final static int FRAME_HEIGHT = 768;
private final JFrame frame;
private final Canvas canvas;
private final List<MyWindow> windowList;
private MyWindow activeWindow;
private MyWindow draggedWindow;
private int draggedWindowOffsetX;
private int draggedWindowOffsetY;
private boolean topBorderLocked;
private boolean rightBorderLocked;
private boolean bottomBorderLocked;
private boolean leftBorderLocked;
private MyWindow highlightedWindow;
private boolean disallowDrag;
public MyScreen() {
windowList = new ArrayList<>();
frame = new JFrame("coderodde GUI simulation");
frame.setSize(FRAME_WIDTH, FRAME_HEIGHT);
frame.setResizable(false);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
final Dimension realScreenDimension =
Toolkit.getDefaultToolkit().getScreenSize();
frame.setLocation((realScreenDimension.width - frame.getWidth()) / 2,
(realScreenDimension.height - frame.getHeight()) / 2);
canvas = new MyCanvas(frame.getWidth(),
frame.getHeight(),
windowList,
this);
frame.add(canvas);
frame.setVisible(true);
}
public void addWindow(final MyWindow window) {
windowList.add(window);
if (activeWindow != null) {
activeWindow.setActive(false);
}
window.setActive(true);
activeWindow = window;
}
public void move(final int x, final int y) {
MyWindow target = null;
for (int i = windowList.size() - 1; i >= 0; --i) {
if (windowList.get(i).windowContainsPoint(x, y)) {
target = windowList.get(i);
break;
}
}
if (target == null) {
if (highlightedWindow != null) {
highlightedWindow.clearBorderHighlights();
highlightedWindow = null;
canvas.repaint();
}
return;
}
if (highlightedWindow != null) {
highlightedWindow.clearBorderHighlights();
highlightedWindow = null;
}
if (target.topBorderContainsPoint(x, y)) {
target.highlightBorder(MyWindow.Border.TOP);
highlightedWindow = target;
} else if (target.bottomBorderContainsPoint(x, y)) {
target.highlightBorder(MyWindow.Border.BOTTOM);
highlightedWindow = target;
}
if (target.rightBorderContainsPoint(x, y)) {
target.highlightBorder(MyWindow.Border.RIGHT);
highlightedWindow = target;
} else if (target.leftBorderContainsPoint(x, y)) {
target.highlightBorder(MyWindow.Border.LEFT);
highlightedWindow = target;
}
canvas.repaint();
}
public void press(final int x, final int y) {
MyWindow newActiveWindow = null;
for (int i = windowList.size() - 1; i >= 0; --i) {
if (windowList.get(i).windowContainsPoint(x, y)) {
newActiveWindow = windowList.remove(i);
break;
}
}
if (newActiveWindow == null) {
return;
}
activeWindow.setActive(false);
activeWindow = newActiveWindow;
windowList.add(activeWindow);
activeWindow.setActive(true);
boolean doResize = false;
if (activeWindow.topBorderContainsPoint(x, y)) {
topBorderLocked = true;
doResize = true;
} else if (activeWindow.bottomBorderContainsPoint(x, y)) {
bottomBorderLocked = true;
doResize = true;
}
if (activeWindow.leftBorderContainsPoint(x, y)) {
leftBorderLocked = true;
doResize = true;
} else if (activeWindow.rightBorderContainsPoint(x, y)) {
rightBorderLocked = true;
doResize = true;
}
if (!doResize && activeWindow.titleBarContainsPoint(x, y)) {
draggedWindow = activeWindow;
draggedWindowOffsetX = x - draggedWindow.getX();
draggedWindowOffsetY = y - draggedWindow.getY();
}
if (doResize) {
draggedWindow = activeWindow;
}
canvas.repaint();
}
public void allowDrag() {
disallowDrag = false;
}
public void disallowDrag() {
disallowDrag = true;
}
public void drag(final int x, final int y) {
if (draggedWindow == null) {
return;
}
if (disallowDrag) {
return;
}
if (!(topBorderLocked
|| rightBorderLocked
|| bottomBorderLocked
|| leftBorderLocked)) {
// Move the entire window.
draggedWindow.setX(x - draggedWindowOffsetX);
draggedWindow.setY(y - draggedWindowOffsetY);
canvas.repaint();
}
// Resize the window.
final int originalX = draggedWindow.getX();
final int originalY = draggedWindow.getY();
if (topBorderLocked) {
draggedWindow.resizeAtTop(y - originalY);
} else if (bottomBorderLocked) {
draggedWindow.setHeight(y - originalY);
}
if (leftBorderLocked) {
draggedWindow.resizeAtLeft(x - originalX);
} else if (rightBorderLocked) {
draggedWindow.setWidth(x - originalX);
}
canvas.repaint();
}
public void releaseMouse() {
draggedWindow = null;
topBorderLocked = false;
leftBorderLocked = false;
bottomBorderLocked = false;
rightBorderLocked = false;
}
List<MyWindow> getWindows() {
return windowList;
}
}
MyWindow.java:
package net.coderodde.gui.simulation;
import java.awt.Color;
import java.awt.Font;
import java.awt.FontMetrics;
import java.awt.Graphics;
public class MyWindow {
public static enum Border {
TOP,
RIGHT,
BOTTOM,
LEFT
}
public final static int MINIMUM_WIDTH = 50;
public final static int MINIMUM_HEIGHT = 50;
private final static int TITLE_BAR_HEIGHT = 30;
private final static Color ACTIVE_TITLE_BAR_BACKGROUND = new Color(255, 150, 100);
private final static Color TITLE_BAR_TEXT_COLOR = Color.WHITE;
private final static Color PASSIVE_TITLE_BAR_BACKGROUND = new Color(200, 200, 200);
private final static Color BORDER_HIGHLIGHT_COLOR = Color.GREEN;
private final static Color BODY_COLOR = new Color(50, 50, 50);
private final static Font TITLE_FONT = new Font("Monospaced", Font.BOLD, 12);
private final static int TITLE_PADDING = 14;
private String title;
private int width;
private int height;
private int x;
private int y;
private boolean active;
private boolean topBorderHightlighted;
private boolean rightBorderHighlighted;
private boolean bottomBorderHightlighted;
private boolean leftBorderHighlighted;
private boolean debug;
public MyWindow(final String title,
final int width,
final int height,
final int x,
final int y) {
this.title = title;
this.width = Math.max(width, MINIMUM_WIDTH);
this.height = Math.max(height, MINIMUM_HEIGHT) + TITLE_BAR_HEIGHT;
this.x = x;
this.y = y;
this.active = false;
}
public void setDebug(final boolean debug) {
this.debug = debug;
}
public boolean isActive() {
return active;
}
public void setActive(final boolean active) {
this.active = active;
}
public void clearBorderHighlights() {
topBorderHightlighted = false;
rightBorderHighlighted = false;
bottomBorderHightlighted = false;
leftBorderHighlighted = false;
}
public void highlightBorder(Border border) {
switch (border) {
case TOP:
topBorderHightlighted = true;
return;
case RIGHT:
rightBorderHighlighted = true;
return;
case BOTTOM:
bottomBorderHightlighted = true;
return;
case LEFT:
leftBorderHighlighted = true;
return;
}
}
public String getTitle() {
return title;
}
public void setTitle(final String title) {
this.title = title;
}
public int getWidth() {
return width;
}
public void setWidth(final int width) {
this.width = Math.max(width, MINIMUM_WIDTH);
}
public int getHeight() {
return height;
}
public void setHeight(final int height) {
if (debug) {
System.out.println("Height changed from " + getHeight() + " to " +
height);
}
this.height = Math.max(height, MINIMUM_HEIGHT);
}
public int getX() {
return x;
}
public int getY() {
return y;
}
public void setX(final int x) {
this.x = x;
}
public void setY(final int y) {
this.y = y;
}
public boolean titleBarContainsPoint(final int x, final int y) {
return getX() <= x
&& x < getX() + width
&& getY() <= y
&& y < getY() + TITLE_BAR_HEIGHT;
}
public boolean windowContainsPoint(final int x, final int y) {
return getX() <= x
&& x < getX() + width
&& getY() <= y
&& y < getY() + height;
}
public boolean topBorderContainsPoint(final int x, final int y) {
return getX() <= x
&& x < getX() + width
&& (y == getY() || y == getY() + 1);
}
public boolean rightBorderContainsPoint(final int x, final int y) {
return (x == getX() + width - 1 || x == getX() + width - 2)
&& getY() <= y
&& y < getY() + height;
}
public boolean bottomBorderContainsPoint(final int xx, final int yy) {
return getX() <= xx
&& xx < getX() + width
&& (yy == getY() + height - 1 || yy == getY() + height - 2);
}
public boolean leftBorderContainsPoint(final int x, final int y) {
return (x == getX() || x == getX() + 1)
&& getY() <= y
&& y < getY() + height;
}
public void draw(final Graphics g) {
final Color titleBarColor = isActive() ?
ACTIVE_TITLE_BAR_BACKGROUND :
PASSIVE_TITLE_BAR_BACKGROUND;
// Draw title bar.
g.setColor(titleBarColor);
g.fillRect(x, y, width, TITLE_BAR_HEIGHT);
g.setColor(TITLE_BAR_TEXT_COLOR);
g.setFont(TITLE_FONT);
g.drawString(getContractedTitle(g.getFontMetrics(TITLE_FONT)),
x + TITLE_PADDING,
y + 18);
// Fill body rectangle.
g.setColor(BODY_COLOR);
g.fillRect(x, y + TITLE_BAR_HEIGHT, width, height - TITLE_BAR_HEIGHT);
// Draw left, right and bottom colors.
g.setColor(titleBarColor);
// Draw left border.
g.drawLine(x, y, x, y + height - 1);
// Draw right border.
g.drawLine(x + width - 1, y, x + width - 1, y + height - 1);
// Draw bottom border
g.drawLine(x, y + height - 1, x + width - 1, y + height - 1);
// Try draw border highlights.
g.setColor(BORDER_HIGHLIGHT_COLOR);
// Top border.
if (topBorderHightlighted) {
g.fillRect(x, y, width, 2);
}
// Left border.
if (leftBorderHighlighted) {
g.fillRect(x, y, 2, height);
}
// Right border.
if (rightBorderHighlighted) {
g.fillRect(x + width - 2, y, 2, height);
}
// Bottom border.
if (bottomBorderHightlighted) {
g.fillRect(x, y + height - 2, width, 2);
}
}
public void resizeAtTop(final int delta) {
final int oldHeight = height;
height = Math.max(MINIMUM_HEIGHT, height - delta);
y += (oldHeight - height);
}
public void resizeAtLeft(final int delta) {
final int oldWidth = width;
width = Math.max(MINIMUM_WIDTH, width - delta);
x += (oldWidth - width);
}
private String getContractedTitle(final FontMetrics fm) {
final int allowedWidth = getWidth() - 2 * TITLE_PADDING;
if (fm.stringWidth(title) <= allowedWidth) {
// Once here, the window title fits entirely in the title bar.
return title;
}
// Once here, we need to contract the string from right.
for (int i = title.length() - 1; i > 0; --i) {
final String contractedTitle = title.substring(0, i);
final String titleWithDots = contractedTitle + "...";
if (fm.stringWidth(titleWithDots) <= allowedWidth) {
return titleWithDots;
}
}
if (fm.stringWidth("...") <= allowedWidth) {
return "...";
}
if (fm.stringWidth("..") <= allowedWidth) {
return "..";
}
return "";
}
}
Simulating a GUI windowing system - follow-up
The previous and initial iteration at Simulating a GUI windowing system
I have essentially cleaned the code based on the only answer.
Now I have:
MyCanvas.java: package net.coderodde.gui.simulation;
import java.awt.Canvas;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import java.awt.event.MouseMotionListener;
import java.util.List;
class MyCanvas extends Canvas {
private final int width;
private final int height;
private final List<MyWindow> windowList;
MyCanvas(final int width,
final int height,
final List<MyWindow> wndList,
final MyScreen screen) {
this.width = width;
this.height = height;
setSize(width, height);
this.windowList = wndList;
final MyMouseListener mml = new MyMouseListener(screen);
addMouseListener(mml);
addMouseMotionListener(mml);
}
@Override
public void paint(final Graphics g) {
g.setColor(Color.BLACK);
g.fillRect(0, 0, width, height);
for (final MyWindow wnd : windowList) {
wnd.draw(g);
}
}
@Override
public void update(final Graphics g) {
paint(g);
}
@Override
public Dimension getPreferredSize() {
return new Dimension(width, height);
}
static class MyMouseListener implements MouseListener,
MouseMotionListener {
private final MyScreen screen;
MyMouseListener(final MyScreen screen) {
this.screen = screen;
}
@Override
public void mouseClicked(MouseEvent e) {
}
@Override
public void mousePressed(MouseEvent e) {
screen.press(e.getX(), e.getY());
}
@Override
public void mouseReleased(MouseEvent e) {
screen.releaseMouse();
}
@Override
public void mouseEntered(MouseEvent e) {
screen.allowDrag();
}
@Override
public void mouseExited(MouseEvent e) {
screen.disallowDrag();
}
@Override
public void mouseDragged(MouseEvent e) {
screen.drag(e.getX(), e.getY());
}
@Override
public void mouseMoved(MouseEvent e) {
screen.move(e.getX(), e.getY());
}
}
}
MyScreen: package net.coderodde.gui.simulation;
import java.awt.Canvas;
import java.awt.Dimension;
import java.util.List;
import java.awt.Toolkit;
import java.util.ArrayList;
import javax.swing.JFrame;
public class MyScreen {
private final static int FRAME_WIDTH = 1024;
private final static int FRAME_HEIGHT = 768;
private final JFrame frame;
private final Canvas canvas;
private final List<MyWindow> windowList;
private MyWindow activeWindow;
private MyWindow draggedWindow;
private int draggedWindowOffsetX;
private int draggedWindowOffsetY;
private boolean topBorderLocked;
private boolean rightBorderLocked;
private boolean bottomBorderLocked;
private boolean leftBorderLocked;
private MyWindow highlightedWindow;
private boolean disallowDrag;
public MyScreen() {
windowList = new ArrayList<>();
frame = new JFrame("coderodde GUI simulation");
frame.setSize(FRAME_WIDTH, FRAME_HEIGHT);
frame.setResizable(false);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
final Dimension realScreenDimension =
Toolkit.getDefaultToolkit().getScreenSize();
frame.setLocation((realScreenDimension.width - frame.getWidth()) / 2,
(realScreenDimension.height - frame.getHeight()) / 2);
canvas = new MyCanvas(frame.getWidth(),
frame.getHeight(),
windowList,
this);
frame.add(canvas);
frame.setVisible(true);
}
public void addWindow(final MyWindow window) {
windowList.add(window);
if (activeWindow != null) {
activeWindow.setActive(false);
}
window.setActive(true);
activeWindow = window;
}
public void move(final int x, final int y) {
MyWindow target = null;
for (int i = windowList.size() - 1; i >= 0; --i) {
if (windowList.get(i).windowContainsPoint(x, y)) {
target = windowList.get(i);
break;
}
}
if (target == null) {
if (highlightedWindow != null) {
highlightedWindow.clearBorderHighlights();
highlightedWindow = null;
canvas.repaint();
}
return;
}
if (highlightedWindow != null) {
highlightedWindow.clearBorderHighlights();
highlightedWindow = null;
}
if (target.topBorderContainsPoint(x, y)) {
target.highlightBorder(MyWindow.Border.TOP);
highlightedWindow = target;
} else if (target.bottomBorderContainsPoint(x, y)) {
target.highlightBorder(MyWindow.Border.BOTTOM);
highlightedWindow = target;
}
if (target.rightBorderContainsPoint(x, y)) {
target.highlightBorder(MyWindow.Border.RIGHT);
highlightedWindow = target;
} else if (target.leftBorderContainsPoint(x, y)) {
target.highlightBorder(MyWindow.Border.LEFT);
highlightedWindow = target;
}
canvas.repaint();
}
public void press(final int x, final int y) {
MyWindow newActiveWindow = null;
for (int i = windowList.size() - 1; i >= 0; --i) {
if (windowList.get(i).windowContainsPoint(x, y)) {
newActiveWindow = windowList.remove(i);
break;
}
}
if (newActiveWindow == null) {
return;
}
activeWindow.setActive(false);
activeWindow = newActiveWindow;
windowList.add(activeWindow);
activeWindow.setActive(true);
boolean doResize = false;
if (activeWindow.topBorderContainsPoint(x, y)) {
topBorderLocked = true;
doResize = true;
} else if (activeWindow.bottomBorderContainsPoint(x, y)) {
bottomBorderLocked = true;
doResize = true;
}
if (activeWindow.leftBorderContainsPoint(x, y)) {
leftBorderLocked = true;
doResize = true;
} else if (activeWindow.rightBorderContainsPoint(x, y)) {
rightBorderLocked = true;
doResize = true;
}
if (!doResize && activeWindow.titleBarContainsPoint(x, y)) {
draggedWindow = activeWindow;
draggedWindowOffsetX = x - draggedWindow.getX();
draggedWindowOffsetY = y - draggedWindow.getY();
}
if (doResize) {
draggedWindow = activeWindow;
}
canvas.repaint();
}
public void allowDrag() {
disallowDrag = false;
}
public void disallowDrag() {
disallowDrag = true;
}
public void drag(final int x, final int y) {
if (draggedWindow == null) {
return;
}
if (disallowDrag) {
return;
}
if (!(topBorderLocked
|| rightBorderLocked
|| bottomBorderLocked
|| leftBorderLocked)) {
// Move the entire window.
draggedWindow.setX(x - draggedWindowOffsetX);
draggedWindow.setY(y - draggedWindowOffsetY);
canvas.repaint();
}
// Resize the window.
final int originalX = draggedWindow.getX();
final int originalY = draggedWindow.getY();
if (topBorderLocked) {
draggedWindow.resizeAtTop(y - originalY);
} else if (bottomBorderLocked) {
draggedWindow.setHeight(y - originalY);
}
if (leftBorderLocked) {
draggedWindow.resizeAtLeft(x - originalX);
} else if (rightBorderLocked) {
draggedWindow.setWidth(x - originalX);
}
canvas.repaint();
}
public void releaseMouse() {
draggedWindow = null;
topBorderLocked = false;
leftBorderLocked = false;
bottomBorderLocked = false;
rightBorderLocked = false;
}
List<MyWindow> getWindows() {
return windowList;
}
}
MyWindow.java: package net.coderodde.gui.simulation;
import java.awt.Color;
import java.awt.Font;
import java.awt.FontMetrics;
import java.awt.Graphics;
public class MyWindow {
public static enum Border {
TOP,
RIGHT,
BOTTOM,
LEFT
}
public final static int MINIMUM_WIDTH = 50;
public final static int MINIMUM_HEIGHT = 50;
private final static int TITLE_BAR_HEIGHT = 30;
private final static Color ACTIVE_TITLE_BAR_BACKGROUND = new Color(255, 150, 100);
private final static Color TITLE_BAR_TEXT_COLOR = Color.WHITE;
private final static Color PASSIVE_TITLE_BAR_BACKGROUND = new Color(200, 200, 200);
private final static Color BORDER_HIGHLIGHT_COLOR = Color.GREEN;
private final static Color BODY_COLOR = new Color(50, 50, 50);
private final static Font TITLE_FONT = new Font("Monospaced", Font.BOLD, 12);
private final static int TITLE_PADDING = 14;
private String title;
private int width;
private int height;
private int x;
private int y;
private boolean active;
private boolean topBorderHightlighted;
private boolean rightBorderHighlighted;
private boolean bottomBorderHightlighted;
private boolean leftBorderHighlighted;
private boolean debug;
public MyWindow(final String title,
final int width,
final int height,
final int x,
final int y) {
this.title = title;
this.width = Math.max(width, MINIMUM_WIDTH);
this.height = Math.max(height, MINIMUM_HEIGHT) + TITLE_BAR_HEIGHT;
this.x = x;
this.y = y;
this.active = false;
}
public void setDebug(final boolean debug) {
this.debug = debug;
}
public boolean isActive() {
return active;
}
public void setActive(final boolean active) {
this.active = active;
}
public void clearBorderHighlights() {
topBorderHightlighted = false;
rightBorderHighlighted = false;
bottomBorderHightlighted = false;
leftBorderHighlighted = false;
}
public void highlightBorder(Border border) {
switch (border) {
case TOP:
topBorderHightlighted = true;
return;
case RIGHT:
rightBorderHighlighted = true;
return;
case BOTTOM:
bottomBorderHightlighted = true;
return;
case LEFT:
leftBorderHighlighted = true;
return;
}
}
public String getTitle() {
return title;
}
public void setTitle(final String title) {
this.title = title;
}
public int getWidth() {
return width;
}
public void setWidth(final int width) {
this.width = Math.max(width, MINIMUM_WIDTH);
}
public int getHeight() {
return height;
}
public void setHeight(final int height) {
if (debug) {
System.out.println("Height changed from " + getHeight() + " to " +
height);
}
this.height = Math.max(height, MINIMUM_HEIGHT);
}
public int getX() {
return x;
}
public int getY() {
return y;
}
public void setX(final int x) {
this.x = x;
}
public void setY(final int y) {
this.y = y;
}
public boolean titleBarContainsPoint(final int x, final int y) {
return getX() <= x
&& x < getX() + width
&& getY() <= y
&& y < getY() + TITLE_BAR_HEIGHT;
}
public boolean windowContainsPoint(final int x, final int y) {
return getX() <= x
&& x < getX() + width
&& getY() <= y
&& y < getY() + height;
}
public boolean topBorderContainsPoint(final int x, final int y) {
return getX() <= x
&& x < getX() + width
&& (y == getY() || y == getY() + 1);
}
public boolean rightBorderContainsPoint(final int x, final int y) {
return (x == getX() + width - 1 || x == getX() + width - 2)
&& getY() <= y
&& y < getY() + height;
}
public boolean bottomBorderContainsPoint(final int xx, final int yy) {
return getX() <= xx
&& xx < getX() + width
&& (yy == getY() + height - 1 || yy == getY() + height - 2);
}
public boolean leftBorderContainsPoint(final int x, final int y) {
return (x == getX() || x == getX() + 1)
&& getY() <= y
&& y < getY() + height;
}
public void draw(final Graphics g) {
final Color titleBarColor = isActive() ?
ACTIVE_TITLE_BAR_BACKGROUND :
PASSIVE_TITLE_BAR_BACKGROUND;
// Draw title bar.
g.setColor(titleBarColor);
g.fillRect(x, y, width, TITLE_BAR_HEIGHT);
g.setColor(TITLE_BAR_TEXT_COLOR);
g.setFont(TITLE_FONT);
g.drawString(getContractedTitle(g.getFontMetrics(TITLE_FONT)),
x + TITLE_PADDING,
y + 18);
// Fill body rectangle.
g.setColor(BODY_COLOR);
g.fillRect(x, y + TITLE_BAR_HEIGHT, width, height - TITLE_BAR_HEIGHT);
// Draw left, right and bottom colors.
g.setColor(titleBarColor);
// Draw left border.
g.drawLine(x, y, x, y + height - 1);
// Draw right border.
g.drawLine(x + width - 1, y, x + width - 1, y + height - 1);
// Draw bottom border
g.drawLine(x, y + height - 1, x + width - 1, y + height - 1);
// Try draw border highlights.
g.setColor(BORDER_HIGHLIGHT_COLOR);
// Top border.
if (topBorderHightlighted) {
g.fillRect(x, y, width, 2);
}
// Left border.
if (leftBorderHighlighted) {
g.fillRect(x, y, 2, height);
}
// Right border.
if (rightBorderHighlighted) {
g.fillRect(x + width - 2, y, 2, height);
}
// Bottom border.
if (bottomBorderHightlighted) {
g.fillRect(x, y + height - 2, width, 2);
}
}
public void resizeAtTop(final int delta) {
final int oldHeight = height;
height = Math.max(MINIMUM_HEIGHT, height - delta);
y += (oldHeight - height);
}
public void resizeAtLeft(final int delta) {
final int oldWidth = width;
width = Math.max(MINIMUM_WIDTH, width - delta);
x += (oldWidth - width);
}
private String getContractedTitle(final FontMetrics fm) {
final int allowedWidth = getWidth() - 2 * TITLE_PADDING;
if (fm.stringWidth(title) <= allowedWidth) {
// Once here, the window title fits entirely in the title bar.
return title;
}
// Once here, we need to contract the string from right.
for (int i = title.length() - 1; i > 0; --i) {
final String contractedTitle = title.substring(0, i);
final String titleWithDots = contractedTitle + "...";
if (fm.stringWidth(titleWithDots) <= allowedWidth) {
return titleWithDots;
}
}
if (fm.stringWidth("...") <= allowedWidth) {
return "...";
}
if (fm.stringWidth("..") <= allowedWidth) {
return "..";
}
return "";
}
}
The Demo.java is not changed.
Now, is the code now kewl and funky enough?