Code Sketch
yoooo...........
Category: Programming
import java.awt.BasicStroke
import java.awt.BorderLayout
import java.awt.Color
import java.awt.Cursor
import java.awt.Dimension
import java.awt.FlowLayout
import java.awt.Font
import java.awt.GradientPaint
import java.awt.Graphics
import java.awt.Graphics2D
import java.awt.RenderingHints
import java.awt.event.ActionEvent
import java.awt.event.ActionListener
import java.awt.event.KeyEvent
import java.awt.event.KeyAdapter
import java.awt.event.MouseAdapter
import java.awt.event.MouseEvent
import java.awt.event.MouseMotionAdapter
import java.awt.image.BufferedImage
import java.io.File
import javax.imageio.ImageIO
import javax.swing.JButton
import javax.swing.JComboBox
import javax.swing.JFileChooser
import javax.swing.JFrame
import javax.swing.JLabel
import javax.swing.JOptionPane
import javax.swing.JPanel
import javax.swing.JTextField
import javax.swing.SwingUtilities
import javax.swing.Timer
import javax.swing.WindowConstants
// ============================================================
// SAFE CONSTANTS
// ============================================================
val CANVAS_WIDTH =
1000
val CANVAS_HEIGHT =
600
val CENTER_X =
500
val CENTER_Y =
300
// ============================================================
// APPLICATION STATE
// ============================================================
var currentColor =
Color.BLACK
var brushSize =
6.0f
var eraserMode =
false
var isDrawing =
false
var lastX =
0
var lastY =
0
var zoomLevel =
1.0
var currentTheme =
"SKY"
var currentStyle =
"3D"
var undoImage:
BufferedImage = null
var redoImage:
BufferedImage = null
// ============================================================
// MAIN FRAME
// ============================================================
val frame =
new JFrame(
"ULTRA LEGEND SMART DRAW"
)
frame.setDefaultCloseOperation(
WindowConstants.EXIT_ON_CLOSE
)
frame.setSize(
1200,
820
)
frame.setLocationRelativeTo(
null
)
// ============================================================
// STATUS LABEL
// ============================================================
val status =
new JLabel(
"Ready - draw something!"
)
status.setFont(
new Font(
"Arial",
Font.BOLD,
15
)
)
// ============================================================
// DRAWING IMAGE
// ============================================================
val drawingImage =
new BufferedImage(
CANVAS_WIDTH,
CANVAS_HEIGHT,
BufferedImage.TYPE_INT_RGB
)
val drawingGraphics =
drawingImage.createGraphics()
drawingGraphics.setRenderingHint(
RenderingHints.KEY_ANTIALIASING,
RenderingHints.VALUE_ANTIALIAS_ON
)
drawingGraphics.setRenderingHint(
RenderingHints.KEY_RENDERING,
RenderingHints.VALUE_RENDER_QUALITY
)
drawingGraphics.setColor(
Color.WHITE
)
drawingGraphics.fillRect(
0,
0,
CANVAS_WIDTH,
CANVAS_HEIGHT
)
// ============================================================
// CANVAS
// ============================================================
val canvas =
new JPanel {
override def paintComponent(
graphics: Graphics
): Unit = {
super.paintComponent(
graphics
)
val g =
graphics.asInstanceOf[Graphics2D]
g.setRenderingHint(
RenderingHints.KEY_ANTIALIASING,
RenderingHints.VALUE_ANTIALIAS_ON
)
g.setRenderingHint(
RenderingHints.KEY_INTERPOLATION,
RenderingHints.VALUE_INTERPOLATION_BICUBIC
)
val imageWidth =
math.max(
1,
(CANVAS_WIDTH * zoomLevel).toInt
)
val imageHeight =
math.max(
1,
(CANVAS_HEIGHT * zoomLevel).toInt
)
val x =
(getWidth - imageWidth) / 2
val y =
(getHeight - imageHeight) / 2
g.drawImage(
drawingImage,
x,
y,
imageWidth,
imageHeight,
null
)
}
}
canvas.setBackground(
Color.WHITE
)
canvas.setPreferredSize(
new Dimension(
CANVAS_WIDTH,
CANVAS_HEIGHT
)
)
canvas.setCursor(
Cursor.getPredefinedCursor(
Cursor.CROSSHAIR_CURSOR
)
)
// ============================================================
// BUTTON HELPER
// ============================================================
def makeButton(
text: String
): JButton = {
val b =
new JButton(
text
)
b.setFocusable(
false
)
b.setFont(
new Font(
"Arial",
Font.BOLD,
12
)
)
b
}
// ============================================================
// TOOLBAR
// ============================================================
val toolbar =
new JPanel(
new FlowLayout(
FlowLayout.LEFT,
4,
4
)
)
val pencilButton =
makeButton(
"PENCIL"
)
val eraserButton =
makeButton(
"ERASER"
)
val undoButton =
makeButton(
"UNDO"
)
val redoButton =
makeButton(
"REDO"
)
val clearButton =
makeButton(
"CLEAR"
)
val saveButton =
makeButton(
"SAVE"
)
val colorizeButton =
makeButton(
"COLORIZE"
)
val threeDButton =
makeButton(
"3D PREVIEW"
)
val zoomInButton =
makeButton(
"ZOOM +"
)
val zoomOutButton =
makeButton(
"ZOOM -"
)
val resetButton =
makeButton(
"RESET"
)
val drawButton =
makeButton(
"DRAW IT"
)
// ============================================================
// WRITE FIELD
// ============================================================
val writeField =
new JTextField(
"CAR",
12
)
// ============================================================
// STYLE SELECTOR
// ============================================================
val styleBox =
new JComboBox[String](
Array(
"3D",
"GLOSSY",
"NEON",
"SOFT",
"COMIC",
"MAGIC",
"GOLD"
)
)
styleBox.setSelectedItem(
"3D"
)
// ============================================================
// SIZE SELECTOR
// ============================================================
val sizeBox =
new JComboBox[String](
Array(
"2",
"4",
"6",
"8",
"10",
"14",
"18",
"24",
"35",
"50"
)
)
sizeBox.setSelectedItem(
"6"
)
// ============================================================
// BUILD TOOLBAR
// ============================================================
toolbar.add(
pencilButton
)
toolbar.add(
eraserButton
)
toolbar.add(
undoButton
)
toolbar.add(
redoButton
)
toolbar.add(
clearButton
)
toolbar.add(
saveButton
)
toolbar.add(
colorizeButton
)
toolbar.add(
threeDButton
)
toolbar.add(
zoomInButton
)
toolbar.add(
zoomOutButton
)
toolbar.add(
resetButton
)
toolbar.add(
new JLabel(
"WRITE:"
)
)
toolbar.add(
writeField
)
toolbar.add(
drawButton
)
toolbar.add(
new JLabel(
"STYLE:"
)
)
toolbar.add(
styleBox
)
toolbar.add(
new JLabel(
"SIZE:"
)
)
toolbar.add(
sizeBox
)
toolbar.add(
new JLabel(
"COLORS:"
)
)
// ============================================================
// COLOR PALETTE
// ============================================================
def addColorButton(
color: Color
): Unit = {
val b =
new JButton(
" "
)
b.setPreferredSize(
new Dimension(
22,
22
)
)
b.setBackground(
color
)
b.setOpaque(
true
)
b.setFocusable(
false
)
b.addActionListener(
new ActionListener {
override def actionPerformed(
e: ActionEvent
): Unit = {
currentColor =
color
eraserMode =
false
status.setText(
"Color selected"
)
}
}
)
toolbar.add(
b
)
}
addColorButton(
Color.BLACK
)
addColorButton(
Color.RED
)
addColorButton(
Color.BLUE
)
addColorButton(
Color.GREEN
)
addColorButton(
Color.YELLOW
)
addColorButton(
Color.ORANGE
)
addColorButton(
Color.MAGENTA
)
addColorButton(
Color.CYAN
)
addColorButton(
Color.PINK
)
addColorButton(
new Color(
128,
64,
0
)
)
// ============================================================
// IMAGE COPY
// ============================================================
def copyImage(
source: BufferedImage
): BufferedImage = {
val result =
new BufferedImage(
CANVAS_WIDTH,
CANVAS_HEIGHT,
BufferedImage.TYPE_INT_RGB
)
val g =
result.createGraphics()
g.drawImage(
source,
0,
0,
null
)
g.dispose()
result
}
// ============================================================
// UNDO MEMORY
// ============================================================
def rememberUndo(): Unit = {
undoImage =
copyImage(
drawingImage
)
redoImage =
null
}
// ============================================================
// RESTORE IMAGE
// ============================================================
def restoreImage(
source: BufferedImage
): Unit = {
drawingGraphics.setColor(
Color.WHITE
)
drawingGraphics.fillRect(
0,
0,
CANVAS_WIDTH,
CANVAS_HEIGHT
)
drawingGraphics.drawImage(
source,
0,
0,
null
)
canvas.repaint()
}
// ============================================================
// CLEAR IMAGE
// ============================================================
def clearImage(): Unit = {
drawingGraphics.setColor(
Color.WHITE
)
drawingGraphics.fillRect(
0,
0,
CANVAS_WIDTH,
CANVAS_HEIGHT
)
canvas.repaint()
}
// ============================================================
// CAR
// ============================================================
def drawCar(): Unit = {
clearImage()
val g =
drawingGraphics
val cx =
CENTER_X
val cy =
CENTER_Y
g.setColor(
new Color(
220,
40,
50
)
)
g.fillRoundRect(
cx - 270,
cy - 40,
540,
125,
35,
35
)
val roof =
new java.awt.Polygon()
roof.addPoint(
cx - 180,
cy - 40
)
roof.addPoint(
cx - 100,
cy - 150
)
roof.addPoint(
cx + 110,
cy - 150
)
roof.addPoint(
cx + 185,
cy - 40
)
g.fillPolygon(
roof
)
g.setColor(
new Color(
125,
215,
245
)
)
g.fillPolygon(
new java.awt.Polygon(
Array(
cx - 145,
cx - 85,
cx - 10,
cx - 10
),
Array(
cy - 44,
cy - 125,
cy - 125,
cy - 44
),
4
)
)
g.fillPolygon(
new java.awt.Polygon(
Array(
cx + 10,
cx + 10,
cx + 115,
cx + 150
),
Array(
cy - 44,
cy - 125,
cy - 125,
cy - 44
),
4
)
)
g.setColor(
Color.BLACK
)
g.fillOval(
cx - 210,
cy + 35,
95,
95
)
g.fillOval(
cx + 115,
cy + 35,
95,
95
)
g.setColor(
Color.LIGHT_GRAY
)
g.fillOval(
cx - 178,
cy + 67,
32,
32
)
g.fillOval(
cx + 147,
cy + 67,
32,
32
)
g.setColor(
Color.YELLOW
)
g.fillOval(
cx - 258,
cy - 12,
30,
27
)
g.fillOval(
cx + 228,
cy - 12,
30,
27
)
g.setColor(
new Color(
35,
35,
40
)
)
g.setStroke(
new BasicStroke(
6
)
)
g.drawRoundRect(
cx - 270,
cy - 40,
540,
125,
35,
35
)
g.dispose()
canvas.repaint()
}
// ============================================================
// HOUSE
// ============================================================
def drawHouse(): Unit = {
clearImage()
val g =
drawingGraphics
val cx =
CENTER_X
g.setColor(
new Color(
245,
205,
125
)
)
g.fillRect(
cx - 205,
230,
410,
260
)
val roof =
new java.awt.Polygon()
roof.addPoint(
cx - 260,
230
)
roof.addPoint(
cx,
45
)
roof.addPoint(
cx + 260,
230
)
g.setColor(
new Color(
180,
55,
45
)
)
g.fillPolygon(
roof
)
g.setColor(
new Color(
125,
78,
45
)
)
g.fillRect(
cx - 50,
340,
100,
150
)
g.setColor(
new Color(
85,
190,
240
)
)
g.fillRect(
cx - 160,
275,
75,
75
)
g.fillRect(
cx + 85,
275,
75,
75
)
g.setColor(
new Color(
70,
165,
75
)
)
g.fillRect(
0,
490,
CANVAS_WIDTH,
110
)
g.setColor(
Color.YELLOW
)
g.fillOval(
70,
50,
105,
105
)
g.dispose()
canvas.repaint()
}
// ============================================================
// TREE
// ============================================================
def drawTree(): Unit = {
clearImage()
val g =
drawingGraphics
val cx =
CENTER_X
g.setColor(
new Color(
70,
165,
75
)
)
g.fillRect(
0,
490,
CANVAS_WIDTH,
110
)
g.setColor(
new Color(
135,
82,
45
)
)
g.fillRoundRect(
cx - 45,
280,
90,
215,
25,
25
)
g.setColor(
new Color(
40,
170,
70
)
)
g.fillOval(
cx - 190,
115,
225,
190
)
g.fillOval(
cx - 15,
85,
230,
215
)
g.fillOval(
cx - 105,
35,
230,
215
)
g.dispose()
canvas.repaint()
}
// ============================================================
// PERSON
// ============================================================
def drawPerson(): Unit = {
clearImage()
val g =
drawingGraphics
val cx =
CENTER_X
val headY =
100
g.setColor(
new Color(
245,
190,
145
)
)
g.fillOval(
cx - 70,
headY,
140,
150
)
g.setColor(
new Color(
50,
35,
25
)
)
g.fillArc(
cx - 73,
headY - 20,
146,
95,
0,
180
)
g.setColor(
Color.BLACK
)
g.fillOval(
cx - 38,
headY + 55,
13,
13
)
g.fillOval(
cx + 25,
headY + 55,
13,
13
)
g.setColor(
new Color(
55,
125,
215
)
)
g.fillRoundRect(
cx - 100,
headY + 145,
200,
180,
30,
30
)
g.setColor(
new Color(
245,
190,
145
)
)
g.setStroke(
new BasicStroke(
27,
BasicStroke.CAP_ROUND,
BasicStroke.JOIN_ROUND
)
)
g.drawLine(
cx - 85,
headY + 180,
cx - 175,
headY + 300
)
g.drawLine(
cx + 85,
headY + 180,
cx + 175,
headY + 300
)
g.setColor(
new Color(
45,
45,
55
)
)
g.setStroke(
new BasicStroke(
40,
BasicStroke.CAP_ROUND,
BasicStroke.JOIN_ROUND
)
)
g.drawLine(
cx - 45,
headY + 305,
cx - 60,
headY + 455
)
g.drawLine(
cx + 45,
headY + 305,
cx + 60,
headY + 455
)
g.dispose()
canvas.repaint()
}
// ============================================================
// ROBOT
// ============================================================
def drawRobot(): Unit = {
clearImage()
val g =
drawingGraphics
val cx =
CENTER_X
val cy =
CENTER_Y
g.setColor(
new Color(
105,
160,
195
)
)
g.fillRoundRect(
cx - 150,
cy - 10,
300,
215,
35,
35
)
g.setColor(
new Color(
160,
195,
215
)
)
g.fillRoundRect(
cx - 175,
cy - 190,
350,
170,
40,
40
)
g.setColor(
Color.CYAN
)
g.fillOval(
cx - 105,
cy - 140,
60,
60
)
g.fillOval(
cx + 45,
cy - 140,
60,
60
)
g.setColor(
Color.DARK_GRAY
)
g.fillRoundRect(
cx - 85,
cy - 65,
170,
35,
15,
15
)
g.setStroke(
new BasicStroke(
9
)
)
g.drawLine(
cx,
cy - 190,
cx,
cy - 255
)
g.setColor(
Color.RED
)
g.fillOval(
cx - 20,
cy - 275,
40,
40
)
g.dispose()
canvas.repaint()
}
// ============================================================
// CAT
// ============================================================
def drawCat(): Unit = {
clearImage()
val g =
drawingGraphics
val cx =
CENTER_X
val cy =
CENTER_Y
g.setColor(
new Color(
180,
180,
190
)
)
g.fillOval(
cx - 140,
cy - 5,
280,
220
)
g.fillOval(
cx - 130,
cy - 160,
260,
210
)
val ear1 =
new java.awt.Polygon()
ear1.addPoint(
cx - 110,
cy - 120
)
ear1.addPoint(
cx - 75,
cy - 220
)
ear1.addPoint(
cx - 25,
cy - 140
)
val ear2 =
new java.awt.Polygon()
ear2.addPoint(
cx + 110,
cy - 120
)
ear2.addPoint(
cx + 75,
cy - 220
)
ear2.addPoint(
cx + 25,
cy - 140
)
g.fillPolygon(
ear1
)
g.fillPolygon(
ear2
)
g.setColor(
new Color(
70,
185,
95
)
)
g.fillOval(
cx - 75,
cy - 85,
45,
45
)
g.fillOval(
cx + 30,
cy - 85,
45,
45
)
g.setColor(
Color.PINK
)
g.fillOval(
cx - 12,
cy - 25,
24,
18
)
g.dispose()
canvas.repaint()
}
// ============================================================
// DOG
// ============================================================
def drawDog(): Unit = {
clearImage()
val g =
drawingGraphics
val cx =
CENTER_X
val cy =
CENTER_Y
g.setColor(
new Color(
180,
120,
70
)
)
g.fillOval(
cx - 160,
cy - 20,
320,
205
)
g.fillOval(
cx - 135,
cy - 170,
270,
230
)
g.setColor(
new Color(
120,
75,
45
)
)
g.fillOval(
cx - 170,
cy - 120,
75,
150
)
g.fillOval(
cx + 95,
cy - 120,
75,
150
)
g.setColor(
Color.BLACK
)
g.fillOval(
cx - 70,
cy - 85,
22,
25
)
g.fillOval(
cx + 48,
cy - 85,
22,
25
)
g.fillOval(
cx - 22,
cy - 35,
44,
32
)
g.dispose()
canvas.repaint()
}
// ============================================================
// BIRD
// ============================================================
def drawBird(): Unit = {
clearImage()
val g =
drawingGraphics
g.setPaint(
new GradientPaint(
0,
0,
new Color(
120,
215,
255
),
0,
CANVAS_HEIGHT,
Color.WHITE
)
)
g.fillRect(
0,
0,
CANVAS_WIDTH,
CANVAS_HEIGHT
)
val cx =
CENTER_X
val cy =
CENTER_Y
g.setColor(
new Color(
65,
130,
225
)
)
g.fillOval(
cx - 145,
cy - 95,
285,
185
)
g.fillOval(
cx + 60,
cy - 145,
135,
130
)
g.setColor(
Color.BLACK
)
g.fillOval(
cx + 140,
cy - 105,
18,
18
)
g.setColor(
Color.ORANGE
)
val beak =
new java.awt.Polygon()
beak.addPoint(
cx + 195,
cy - 80
)
beak.addPoint(
cx + 260,
cy - 55
)
beak.addPoint(
cx + 195,
cy - 35
)
g.fillPolygon(
beak
)
g.dispose()
canvas.repaint()
}
// ============================================================
// FLOWER
// ============================================================
def drawFlower(): Unit = {
clearImage()
val g =
drawingGraphics
val cx =
CENTER_X
val cy =
230
g.setColor(
new Color(
45,
155,
60
)
)
g.setStroke(
new BasicStroke(
15
)
)
g.drawLine(
cx,
cy + 55,
cx,
510
)
val colors =
Array(
Color.RED,
Color.PINK,
Color.MAGENTA,
Color.ORANGE,
new Color(145,80,220),
new Color(255,80,120)
)
var i =
0
while (
i < 6
) {
val angle =
i * math.Pi / 3.0
val px =
cx +
(math.cos(angle) * 80).toInt -
50
val py =
cy +
(math.sin(angle) * 80).toInt -
50
g.setColor(
colors(i)
)
g.fillOval(
px,
py,
100,
100
)
i += 1
}
g.setColor(
Color.YELLOW
)
g.fillOval(
cx - 50,
cy - 50,
100,
100
)
g.dispose()
canvas.repaint()
}
// ============================================================
// STAR
// ============================================================
def drawStar(): Unit = {
clearImage()
val g =
drawingGraphics
val star =
new java.awt.Polygon()
var i =
0
while (
i < 10
) {
val angle =
-math.Pi / 2 +
i * math.Pi / 5.0
val radius =
if (
i % 2 == 0
) {
190.0
} else {
80.0
}
star.addPoint(
CENTER_X +
(math.cos(angle) * radius).toInt,
CENTER_Y +
(math.sin(angle) * radius).toInt
)
i += 1
}
g.setColor(
new Color(
255,
210,
0
)
)
g.fillPolygon(
star
)
g.dispose()
canvas.repaint()
}
// ============================================================
// HEART
// ============================================================
def drawHeart(): Unit = {
clearImage()
val g =
drawingGraphics
val path =
new java.awt.geom.Path2D.Double()
path.moveTo(
CENTER_X,
CENTER_Y + 190
)
path.curveTo(
CENTER_X - 270,
CENTER_Y + 20,
CENTER_X - 170,
CENTER_Y - 175,
CENTER_X,
CENTER_Y - 45
)
path.curveTo(
CENTER_X + 170,
CENTER_Y - 175,
CENTER_X + 270,
CENTER_Y + 20,
CENTER_X,
CENTER_Y + 190
)
g.setColor(
Color.RED
)
g.fill(
path
)
g.dispose()
canvas.repaint()
}
// ============================================================
// GENERIC DRAW
// ============================================================
def drawGeneric(): Unit = {
clearImage()
val g =
drawingGraphics
g.setColor(
new Color(
75,
135,
225
)
)
g.fillRoundRect(
280,
150,
440,
300,
40,
40
)
g.setColor(
Color.YELLOW
)
g.fillOval(
430,
230,
140,
140
)
g.dispose()
canvas.repaint()
}
// ============================================================
// TEXT TO DRAW
// ============================================================
def drawFromText(
value: String
): Unit = {
val text =
value
.trim
.toLowerCase
if (
text.length == 0
) {
status.setText(
"Write something first."
)
return
}
rememberUndo()
if (
text.indexOf("car") >= 0 ||
text.indexOf("auto") >= 0 ||
text.indexOf("taxi") >= 0 ||
text.indexOf("bus") >= 0 ||
text.indexOf("truck") >= 0 ||
text.indexOf("bike") >= 0
) {
drawCar()
} else if (
text.indexOf("house") >= 0 ||
text.indexOf("home") >= 0 ||
text.indexOf("building") >= 0 ||
text.indexOf("school") >= 0
) {
drawHouse()
} else if (
text.indexOf("tree") >= 0 ||
text.indexOf("forest") >= 0 ||
text.indexOf("plant") >= 0
) {
drawTree()
} else if (
text.indexOf("boy") >= 0 ||
text.indexOf("girl") >= 0 ||
text.indexOf("man") >= 0 ||
text.indexOf("woman") >= 0 ||
text.indexOf("person") >= 0 ||
text.indexOf("human") >= 0 ||
text.indexOf("child") >= 0 ||
text.indexOf("baby") >= 0 ||
text.indexOf("doctor") >= 0 ||
text.indexOf("teacher") >= 0
) {
drawPerson()
} else if (
text.indexOf("robot") >= 0
) {
drawRobot()
} else if (
text.indexOf("cat") >= 0 ||
text.indexOf("kitten") >= 0
) {
drawCat()
} else if (
text.indexOf("dog") >= 0 ||
text.indexOf("puppy") >= 0
) {
drawDog()
} else if (
text.indexOf("bird") >= 0 ||
text.indexOf("eagle") >= 0 ||
text.indexOf("parrot") >= 0
) {
drawBird()
} else if (
text.indexOf("flower") >= 0 ||
text.indexOf("rose") >= 0
) {
drawFlower()
} else if (
text.indexOf("star") >= 0
) {
drawStar()
} else if (
text.indexOf("heart") >= 0
) {
drawHeart()
} else if (
text.indexOf("pizza") >= 0 ||
text.indexOf("burger") >= 0 ||
text.indexOf("cake") >= 0
) {
drawFood()
} else if (
text.indexOf("fish") >= 0 ||
text.indexOf("shark") >= 0 ||
text.indexOf("whale") >= 0
) {
drawFish()
} else if (
text.indexOf("planet") >= 0 ||
text.indexOf("earth") >= 0 ||
text.indexOf("mars") >= 0 ||
text.indexOf("moon") >= 0 ||
text.indexOf("galaxy") >= 0
) {
drawSpace()
} else {
drawGeneric()
}
status.setText(
"Created: " +
value
)
canvas.repaint()
}
// ============================================================
// FOOD
// ============================================================
def drawFood(): Unit = {
clearImage()
val g =
drawingGraphics
g.setColor(
new Color(
240,
175,
50
)
)
g.fillOval(
CENTER_X - 190,
CENTER_Y - 100,
380,
200
)
g.setColor(
Color.RED
)
g.fillOval(
CENTER_X - 120,
CENTER_Y - 10,
38,
38
)
g.fillOval(
CENTER_X + 45,
CENTER_Y - 25,
38,
38
)
g.dispose()
canvas.repaint()
}
// ============================================================
// FISH
// ============================================================
def drawFish(): Unit = {
clearImage()
val g =
drawingGraphics
g.setColor(
new Color(
70,
155,
230
)
)
g.fillOval(
CENTER_X - 175,
CENTER_Y - 90,
350,
180
)
val tail =
new java.awt.Polygon()
tail.addPoint(
CENTER_X + 150,
CENTER_Y
)
tail.addPoint(
CENTER_X + 260,
CENTER_Y - 90
)
tail.addPoint(
CENTER_X + 260,
CENTER_Y + 90
)
g.fillPolygon(
tail
)
g.setColor(
Color.BLACK
)
g.fillOval(
CENTER_X - 100,
CENTER_Y - 35,
22,
22
)
g.dispose()
canvas.repaint()
}
// ============================================================
// SPACE
// ============================================================
def drawSpace(): Unit = {
clearImage()
val g =
drawingGraphics
g.setColor(
new Color(
5,
10,
35
)
)
g.fillRect(
0,
0,
CANVAS_WIDTH,
CANVAS_HEIGHT
)
g.setColor(
Color.WHITE
)
var i =
0
while (
i < 75
) {
val x =
(i * 73) % CANVAS_WIDTH
val y =
(i * 43) % 400
g.fillOval(
x,
y,
4,
4
)
i += 1
}
g.setColor(
new Color(
90,
150,
240
)
)
g.fillOval(
CENTER_X - 120,
CENTER_Y - 120,
240,
240
)
g.dispose()
canvas.repaint()
}
// ============================================================
// BACKGROUND LIST
// ============================================================
val backgroundList =
Array(
"SKY",
"SUNNY DAY",
"SUNRISE",
"SUNSET",
"GOLDEN SUNSET",
"NIGHT",
"NIGHT SKY",
"STAR NIGHT",
"SPACE",
"GALAXY",
"DEEP SPACE",
"COSMIC",
"OCEAN",
"DEEP OCEAN",
"UNDERWATER",
"BLUE OCEAN",
"BEACH",
"TROPICAL BEACH",
"ISLAND",
"PARADISE",
"FOREST",
"DEEP FOREST",
"GREEN VALLEY",
"MOUNTAIN",
"SNOW",
"SNOW WORLD",
"ICE",
"DESERT",
"RAINBOW",
"CLOUD WORLD",
"CITY",
"CITY NIGHT",
"NEON CITY",
"FUTURE CITY",
"CYBER CITY",
"MAGIC",
"MAGICAL WORLD",
"FANTASY",
"FAIRY WORLD",
"CARTOON WORLD",
"COMIC WORLD",
"CANDY WORLD",
"PINK DREAM",
"BLUE DREAM",
"PURPLE DREAM",
"GOLDEN WORLD",
"ROYAL WORLD",
"FIRE WORLD",
"VOLCANO",
"AUTUMN",
"SPRING",
"SUMMER",
"WINTER",
"JUNGLE",
"DREAM WORLD"
)
// ============================================================
// BACKGROUND COLOR SELECTOR
// ============================================================
def getThemeColors(
theme: String
): Array[Color] = {
val t =
theme.toUpperCase
if (
t.indexOf("SUNSET") >= 0
) {
Array(
new Color(255,120,80),
new Color(105,55,155)
)
} else if (
t.indexOf("SUNRISE") >= 0
) {
Array(
new Color(255,180,105),
new Color(255,230,155)
)
} else if (
t.indexOf("NIGHT") >= 0
) {
Array(
new Color(10,18,65),
new Color(60,45,115)
)
} else if (
t.indexOf("SPACE") >= 0 ||
t.indexOf("GALAXY") >= 0 ||
t.indexOf("COSMIC") >= 0
) {
Array(
new Color(3,5,25),
new Color(60,10,100)
)
} else if (
t.indexOf("OCEAN") >= 0 ||
t.indexOf("UNDERWATER") >= 0
) {
Array(
new Color(100,220,255),
new Color(10,80,180)
)
} else if (
t.indexOf("BEACH") >= 0 ||
t.indexOf("ISLAND") >= 0 ||
t.indexOf("PARADISE") >= 0
) {
Array(
new Color(100,220,255),
new Color(245,205,125)
)
} else if (
t.indexOf("FOREST") >= 0 ||
t.indexOf("JUNGLE") >= 0 ||
t.indexOf("GREEN") >= 0
) {
Array(
new Color(175,235,205),
new Color(50,145,70)
)
} else if (
t.indexOf("MOUNTAIN") >= 0
) {
Array(
new Color(175,220,255),
new Color(105,130,160)
)
} else if (
t.indexOf("SNOW") >= 0 ||
t.indexOf("ICE") >= 0
) {
Array(
Color.WHITE,
new Color(145,215,250)
)
} else if (
t.indexOf("DESERT") >= 0 ||
t.indexOf("AUTUMN") >= 0
) {
Array(
new Color(255,220,150),
new Color(205,145,80)
)
} else if (
t.indexOf("CITY") >= 0 ||
t.indexOf("FUTURE") >= 0 ||
t.indexOf("CYBER") >= 0
) {
Array(
new Color(125,150,190),
new Color(40,50,70)
)
} else if (
t.indexOf("NEON") >= 0
) {
Array(
new Color(8,15,55),
new Color(105,0,145)
)
} else if (
t.indexOf("MAGIC") >= 0 ||
t.indexOf("FANTASY") >= 0 ||
t.indexOf("FAIRY") >= 0
) {
Array(
new Color(215,185,255),
new Color(105,55,165)
)
} else if (
t.indexOf("CANDY") >= 0 ||
t.indexOf("PINK") >= 0
) {
Array(
new Color(255,195,225),
new Color(245,95,175)
)
} else if (
t.indexOf("GOLD") >= 0 ||
t.indexOf("ROYAL") >= 0
) {
Array(
new Color(255,235,135),
new Color(205,145,35)
)
} else if (
t.indexOf("FIRE") >= 0 ||
t.indexOf("VOLCANO") >= 0
) {
Array(
new Color(255,150,70),
new Color(180,35,35)
)
} else if (
t.indexOf("PURPLE") >= 0
) {
Array(
new Color(220,190,255),
new Color(105,45,170)
)
} else if (
t.indexOf("BLUE") >= 0
) {
Array(
new Color(185,230,255),
new Color(60,125,225)
)
} else {
Array(
new Color(165,220,255),
new Color(95,180,100)
)
}
}
// ============================================================
// CREATE BACKGROUND
// ============================================================
def createBackground(
theme: String
): BufferedImage = {
val result =
new BufferedImage(
CANVAS_WIDTH,
CANVAS_HEIGHT,
BufferedImage.TYPE_INT_RGB
)
val g =
result.createGraphics()
val colors =
getThemeColors(
theme
)
g.setPaint(
new GradientPaint(
0,
0,
colors(0),
0,
CANVAS_HEIGHT,
colors(1)
)
)
g.fillRect(
0,
0,
CANVAS_WIDTH,
CANVAS_HEIGHT
)
val t =
theme.toUpperCase
if (
t.indexOf("NIGHT") < 0 &&
t.indexOf("SPACE") < 0 &&
t.indexOf("GALAXY") < 0 &&
t.indexOf("NEON") < 0
) {
g.setColor(
new Color(
255,
255,
255,
120
)
)
g.fillOval(
60,
55,
150,
50
)
g.fillOval(
105,
30,
105,
70
)
g.fillOval(
700,
80,
150,
50
)
g.fillOval(
750,
55,
105,
70
)
}
if (
t == "SKY" ||
t.indexOf("SUN") >= 0 ||
t.indexOf("BEACH") >= 0
) {
g.setColor(
new Color(
255,
210,
55
)
)
g.fillOval(
830,
45,
105,
105
)
}
if (
t.indexOf("NIGHT") >= 0 ||
t.indexOf("SPACE") >= 0 ||
t.indexOf("GALAXY") >= 0 ||
t.indexOf("MAGIC") >= 0 ||
t.indexOf("FANTASY") >= 0
) {
g.setColor(
Color.WHITE
)
var i =
0
while (
i < 100
) {
val sx =
(i * 71) % CANVAS_WIDTH
val sy =
(i * 43) % 370
g.fillOval(
sx,
sy,
3 + (i % 4),
3 + (i % 4)
)
i += 1
}
}
if (
t.indexOf("RAINBOW") >= 0
) {
val rainbow =
Array(
Color.RED,
Color.ORANGE,
Color.YELLOW,
Color.GREEN,
Color.CYAN,
Color.BLUE,
Color.MAGENTA
)
var r =
0
while (
r < rainbow.length
) {
g.setColor(
rainbow(r)
)
g.setStroke(
new BasicStroke(
9
)
)
g.drawArc(
220,
125 + r * 9,
560 - r * 18,
350 - r * 18,
0,
180
)
r += 1
}
}
if (
t.indexOf("SPACE") < 0 &&
t.indexOf("GALAXY") < 0 &&
t.indexOf("NIGHT") < 0 &&
t.indexOf("NEON") < 0
) {
if (
t.indexOf("OCEAN") >= 0 ||
t.indexOf("UNDERWATER") >= 0
) {
g.setColor(
new Color(
20,
120,
190,
190
)
)
} else {
g.setColor(
new Color(
70,
165,
75,
175
)
)
}
g.fillRect(
0,
490,
CANVAS_WIDTH,
110
)
}
if (
t.indexOf("CITY") >= 0 ||
t.indexOf("FUTURE") >= 0 ||
t.indexOf("CYBER") >= 0
) {
var b =
0
while (
b < 10
) {
val bx =
b * 105
val bh =
120 +
(b % 4) * 50
g.setColor(
new Color(
35,
45,
65,
235
)
)
g.fillRect(
bx,
490 - bh,
80,
bh
)
g.setColor(
if (
t.indexOf("NEON") >= 0
) {
Color.CYAN
} else {
Color.YELLOW
}
)
var wy =
490 - bh + 20
while (
wy < 480
) {
g.fillRect(
bx + 15,
wy,
12,
18
)
wy += 35
}
b += 1
}
}
g.dispose()
result
}
// ============================================================
// REMOVE WHITE BACKGROUND OF SKETCH
// ============================================================
def isWhitePixel(
rgb: Int
): Boolean = {
val red =
(rgb >> 16) & 255
val green =
(rgb >> 8) & 255
val blue =
rgb & 255
red >= 245 &&
green >= 245 &&
blue >= 245
}
// ============================================================
// COMPOSITE DRAWING
// ============================================================
def composeDrawing(
background: BufferedImage
): BufferedImage = {
val result =
copyImage(
background
)
var x =
0
while (
x < CANVAS_WIDTH
) {
var y =
0
while (
y < CANVAS_HEIGHT
) {
val rgb =
drawingImage.getRGB(
x,
y
)
if (
!isWhitePixel(
rgb
)
) {
result.setRGB(
x,
y,
rgb
)
}
y += 1
}
x += 1
}
result
}
// ============================================================
// APPLY STYLE
// ============================================================
def applyStyle(
theme: String,
style: String
): BufferedImage = {
val background =
createBackground(
theme
)
val base =
composeDrawing(
background
)
val result =
copyImage(
base
)
val g =
result.createGraphics()
if (
style == "3D"
) {
var d =
20
while (
d > 0
) {
g.setColor(
new Color(
0,
0,
0,
10
)
)
g.drawImage(
base,
d,
d,
null
)
d -= 1
}
g.drawImage(
base,
0,
0,
null
)
}
if (
style == "GLOSSY"
) {
g.setColor(
new Color(
255,
255,
255,
50
)
)
g.fillRoundRect(
20,
20,
960,
130,
35,
35
)
}
if (
style == "NEON"
) {
g.setColor(
new Color(
0,
255,
255,
100
)
)
g.setStroke(
new BasicStroke(
12
)
)
g.drawRoundRect(
10,
10,
980,
580,
30,
30
)
g.setColor(
new Color(
255,
0,
255,
110
)
)
g.setStroke(
new BasicStroke(
4
)
)
g.drawRoundRect(
20,
20,
960,
560,
25,
25
)
}
if (
style == "SOFT"
) {
g.setColor(
new Color(
255,
255,
255,
35
)
)
g.fillRect(
0,
0,
CANVAS_WIDTH,
CANVAS_HEIGHT
)
}
if (
style == "COMIC"
) {
g.setColor(
new Color(
10,
10,
10,
150
)
)
g.setStroke(
new BasicStroke(
8
)
)
g.drawRoundRect(
8,
8,
984,
584,
25,
25
)
}
if (
style == "MAGIC"
) {
g.setColor(
Color.WHITE
)
var m =
0
while (
m < 45
) {
val px =
(m * 83) % CANVAS_WIDTH
val py =
(m * 47) % CANVAS_HEIGHT
g.fillOval(
px,
py,
5,
5
)
m += 1
}
}
if (
style == "GOLD"
) {
g.setColor(
new Color(
255,
215,
70,
100
)
)
g.setStroke(
new BasicStroke(
10
)
)
g.drawRoundRect(
12,
12,
976,
576,
30,
30
)
}
g.dispose()
result
}
// ============================================================
// COLORIZE DIALOG
// ============================================================
def openColorizeDialog(): Unit = {
val backgroundBox =
new JComboBox[String](
backgroundList
)
backgroundBox.setSelectedItem(
currentTheme
)
val styleChoice =
new JComboBox[String](
Array(
"3D",
"GLOSSY",
"NEON",
"SOFT",
"COMIC",
"MAGIC",
"GOLD"
)
)
styleChoice.setSelectedItem(
currentStyle
)
val panel =
new JPanel(
new BorderLayout(
10,
10
)
)
val controls =
new JPanel(
new FlowLayout(
FlowLayout.LEFT
)
)
controls.add(
new JLabel(
"BACKGROUND:"
)
)
controls.add(
backgroundBox
)
controls.add(
new JLabel(
"STYLE:"
)
)
controls.add(
styleChoice
)
panel.add(
new JLabel(
"ULTRA COLORIZE"
),
BorderLayout.NORTH
)
panel.add(
controls,
BorderLayout.CENTER
)
val answer =
JOptionPane.showConfirmDialog(
frame,
panel,
"COLORIZE DRAWING",
JOptionPane.OK_CANCEL_OPTION,
JOptionPane.PLAIN_MESSAGE
)
if (
answer ==
JOptionPane.OK_OPTION
) {
rememberUndo()
currentTheme =
backgroundBox
.getSelectedItem
.toString
currentStyle =
styleChoice
.getSelectedItem
.toString
val result =
applyStyle(
currentTheme,
currentStyle
)
restoreImage(
result
)
canvas.repaint()
status.setText(
"Colorize complete: " +
currentTheme
)
}
}
// ============================================================
// 3D PREVIEW
// ============================================================
def show3DPreview(): Unit = {
val image =
applyStyle(
currentTheme,
"3D"
)
val previewFrame =
new JFrame(
"ULTRA 3D PREVIEW"
)
previewFrame.setDefaultCloseOperation(
WindowConstants.DISPOSE_ON_CLOSE
)
previewFrame.setSize(
1100,
760
)
previewFrame.setLocationRelativeTo(
frame
)
val previewPanel =
new JPanel {
override def paintComponent(
graphics: Graphics
): Unit = {
super.paintComponent(
graphics
)
val g =
graphics.asInstanceOf[
Graphics2D
]
g.setRenderingHint(
RenderingHints.KEY_INTERPOLATION,
RenderingHints.VALUE_INTERPOLATION_BICUBIC
)
val availableWidth =
getWidth - 40
val availableHeight =
getHeight - 70
val scale =
math.min(
availableWidth.toDouble /
image.getWidth,
availableHeight.toDouble /
image.getHeight
)
val imageWidth =
math.max(
1,
(image.getWidth * scale).toInt
)
val imageHeight =
math.max(
1,
(image.getHeight * scale).toInt
)
val x =
(getWidth - imageWidth) / 2
val y =
(getHeight - imageHeight) / 2
g.drawImage(
image,
x,
y,
imageWidth,
imageHeight,
null
)
}
}
val animateButton =
new JButton(
"ANIMATE"
)
val stopButton =
new JButton(
"STOP"
)
val saveButton =
new JButton(
"SAVE 3D"
)
animateButton.setFocusable(
false
)
stopButton.setFocusable(
false
)
saveButton.setFocusable(
false
)
val animationTimer =
new Timer(
60,
new ActionListener {
override def actionPerformed(
e: ActionEvent
): Unit = {
if (
animationEnabled
) {
animationOffset =
animationOffset + 1
previewPanel.repaint()
}
}
}
)
var previewAnimation =
false
animateButton.addActionListener(
new ActionListener {
override def actionPerformed(
e: ActionEvent
): Unit = {
previewAnimation =
true
animationEnabled =
true
animationTimer.start()
}
}
)
stopButton.addActionListener(
new ActionListener {
override def actionPerformed(
e: ActionEvent
): Unit = {
previewAnimation =
false
animationEnabled =
false
animationTimer.stop()
}
}
)
saveButton.addActionListener(
new ActionListener {
override def actionPerformed(
e: ActionEvent
): Unit = {
saveImageObject(
image,
previewFrame
)
}
}
)
previewFrame.setLayout(
new BorderLayout()
)
previewFrame.add(
previewPanel,
BorderLayout.CENTER
)
val buttons =
new JPanel(
new FlowLayout(
FlowLayout.CENTER
)
)
buttons.add(
animateButton
)
buttons.add(
stopButton
)
buttons.add(
saveButton
)
previewFrame.add(
buttons,
BorderLayout.SOUTH
)
previewFrame.setVisible(
true
)
}
// ============================================================
// ANIMATION STATE
// ============================================================
var animationEnabled =
false
var animationOffset =
0
// ============================================================
// SAVE IMAGE OBJECT
// ============================================================
def saveImageObject(
image: BufferedImage,
owner: JFrame
): Unit = {
val chooser =
new JFileChooser()
if (
chooser.showSaveDialog(
owner
) ==
JFileChooser.APPROVE_OPTION
) {
try {
var file =
chooser.getSelectedFile
if (
!file.getName
.toLowerCase
.endsWith(
".png"
)
) {
file =
new File(
file.getAbsolutePath +
".png"
)
}
ImageIO.write(
image,
"png",
file
)
status.setText(
"Image saved!"
)
} catch {
case ex: Exception =>
JOptionPane.showMessageDialog(
owner,
ex.getMessage,
"Save Error",
JOptionPane.ERROR_MESSAGE
)
}
}
}
// ============================================================
// SAVE CURRENT
// ============================================================
def saveCurrentImage(): Unit = {
saveImageObject(
drawingImage,
frame
)
}
// ============================================================
// PENCIL
// ============================================================
pencilButton.addActionListener(
new ActionListener {
override def actionPerformed(
e: ActionEvent
): Unit = {
eraserMode =
false
status.setText(
"Pencil selected"
)
}
}
)
// ============================================================
// ERASER
// ============================================================
eraserButton.addActionListener(
new ActionListener {
override def actionPerformed(
e: ActionEvent
): Unit = {
eraserMode =
true
status.setText(
"Eraser selected"
)
}
}
)
// ============================================================
// SIZE
// ============================================================
sizeBox.addActionListener(
new ActionListener {
override def actionPerformed(
e: ActionEvent
): Unit = {
try {
brushSize =
sizeBox
.getSelectedItem
.toString
.toFloat
} catch {
case _: Exception =>
}
}
}
)
// ============================================================
// DRAW
// ============================================================
drawButton.addActionListener(
new ActionListener {
override def actionPerformed(
e: ActionEvent
): Unit = {
drawFromText(
writeField.getText
)
}
}
)
writeField.addActionListener(
new ActionListener {
override def actionPerformed(
e: ActionEvent
): Unit = {
drawFromText(
writeField.getText
)
}
}
)
// ============================================================
// COLORIZE
// ============================================================
colorizeButton.addActionListener(
new ActionListener {
override def actionPerformed(
e: ActionEvent
): Unit = {
openColorizeDialog()
}
}
)
// ============================================================
// 3D
// ============================================================
threeDButton.addActionListener(
new ActionListener {
override def actionPerformed(
e: ActionEvent
): Unit = {
show3DPreview()
}
}
)
// ============================================================
// UNDO
// ============================================================
undoButton.addActionListener(
new ActionListener {
override def actionPerformed(
e: ActionEvent
): Unit = {
if (
undoImage != null
) {
redoImage =
copyImage(
drawingImage
)
restoreImage(
undoImage
)
undoImage =
null
status.setText(
"Undo complete"
)
}
}
}
)
// ============================================================
// REDO
// ============================================================
redoButton.addActionListener(
new ActionListener {
override def actionPerformed(
e: ActionEvent
): Unit = {
if (
redoImage != null
) {
undoImage =
copyImage(
drawingImage
)
restoreImage(
redoImage
)
redoImage =
null
status.setText(
"Redo complete"
)
}
}
}
)
// ============================================================
// CLEAR
// ============================================================
clearButton.addActionListener(
new ActionListener {
override def actionPerformed(
e: ActionEvent
): Unit = {
rememberUndo()
clearImage()
status.setText(
"Canvas cleared"
)
}
}
)
// ============================================================
// SAVE
// ============================================================
saveButton.addActionListener(
new ActionListener {
override def actionPerformed(
e: ActionEvent
): Unit = {
saveCurrentImage()
}
}
)
// ============================================================
// ZOOM IN
// ============================================================
zoomInButton.addActionListener(
new ActionListener {
override def actionPerformed(
e: ActionEvent
): Unit = {
zoomLevel =
math.min(
2.0,
zoomLevel + 0.10
)
canvas.repaint()
status.setText(
"Zoom: " +
math.round(
zoomLevel * 100
) +
"%"
)
}
}
)
// ============================================================
// ZOOM OUT
// ============================================================
zoomOutButton.addActionListener(
new ActionListener {
override def actionPerformed(
e: ActionEvent
): Unit = {
zoomLevel =
math.max(
0.60,
zoomLevel - 0.10
)
canvas.repaint()
status.setText(
"Zoom: " +
math.round(
zoomLevel * 100
) +
"%"
)
}
}
)
// ============================================================
// RESET
// ============================================================
resetButton.addActionListener(
new ActionListener {
override def actionPerformed(
e: ActionEvent
): Unit = {
zoomLevel =
1.0
currentTheme =
"SKY"
currentStyle =
"3D"
canvas.repaint()
status.setText(
"View reset"
)
}
}
)
// ============================================================
// MOUSE DRAWING
// ============================================================
canvas.addMouseListener(
new MouseAdapter {
override def mousePressed(
e: MouseEvent
): Unit = {
rememberUndo()
isDrawing =
true
lastX =
math.max(
0,
math.min(
CANVAS_WIDTH - 1,
e.getX
)
)
lastY =
math.max(
0,
math.min(
CANVAS_HEIGHT - 1,
e.getY
)
)
if (
eraserMode
) {
drawingGraphics.setColor(
Color.WHITE
)
} else {
drawingGraphics.setColor(
currentColor
)
}
val s =
math.max(
1,
brushSize.toInt
)
drawingGraphics.fillOval(
lastX - s / 2,
lastY - s / 2,
s,
s
)
canvas.repaint()
}
override def mouseReleased(
e: MouseEvent
): Unit = {
isDrawing =
false
}
}
)
// ============================================================
// MOUSE DRAGGING
// ============================================================
canvas.addMouseMotionListener(
new MouseMotionAdapter {
override def mouseDragged(
e: MouseEvent
): Unit = {
if (
isDrawing
) {
val x =
math.max(
0,
math.min(
CANVAS_WIDTH - 1,
e.getX
)
)
val y =
math.max(
0,
math.min(
CANVAS_HEIGHT - 1,
e.getY
)
)
if (
eraserMode
) {
drawingGraphics.setColor(
Color.WHITE
)
} else {
drawingGraphics.setColor(
currentColor
)
}
drawingGraphics.setStroke(
new BasicStroke(
brushSize,
BasicStroke.CAP_ROUND,
BasicStroke.JOIN_ROUND
)
)
drawingGraphics.drawLine(
lastX,
lastY,
x,
y
)
lastX =
x
lastY =
y
canvas.repaint()
}
}
}
)
// ============================================================
// KEYBOARD SHORTCUTS
// ============================================================
canvas.addKeyListener(
new KeyAdapter {
override def keyPressed(
e: KeyEvent
): Unit = {
if (
e.isControlDown &&
e.getKeyCode ==
KeyEvent.VK_Z
) {
undoButton.doClick()
}
if (
e.isControlDown &&
e.getKeyCode ==
KeyEvent.VK_Y
) {
redoButton.doClick()
}
if (
e.getKeyCode ==
KeyEvent.VK_F2
) {
colorizeButton.doClick()
}
if (
e.getKeyCode ==
KeyEvent.VK_F3
) {
threeDButton.doClick()
}
}
}
)
// ============================================================
// BOTTOM BAR
// ============================================================
val bottom =
new JPanel(
new FlowLayout(
FlowLayout.LEFT,
8,
5
)
)
bottom.add(
status
)
bottom.add(
new JLabel(
"F2 Colorize | F3 3D | Ctrl+Z Undo | Ctrl+Y Redo"
)
)
// ============================================================
// LAYOUT
// ============================================================
frame.setLayout(
new BorderLayout()
)
frame.add(
toolbar,
BorderLayout.NORTH
)
frame.add(
canvas,
BorderLayout.CENTER
)
frame.add(
bottom,
BorderLayout.SOUTH
)
// ============================================================
// START
// ============================================================
SwingUtilities.invokeLater(
new Runnable {
override def run(): Unit = {
frame.setVisible(
true
)
canvas.requestFocusInWindow()
frame.requestFocusInWindow()
status.setText(
"ULTRA LEGEND READY!"
)
}
}
)