Code Sketch
sniper_0718
Category: Art
import scala.swing._
import scala.swing.event._
import java.awt.Color
import java.awt.Font
import java.awt.Graphics2D
import java.awt.event.MouseEvent
import java.net.URL
import javax.swing.ImageIcon
import scala.collection.mutable
import scala.concurrent.ExecutionContext.Implicits.global
object KojoMultiPCApp {
val registeredUsers = mutable.Map[String, String](
"bhimraj" -> "praxnya",
"user1" -> "123",
"user2" -> "456"
)
val onlineUsers = mutable.Set[String]()
val postsList = mutable.ListBuffer[(String, String)]()
val friendRequests = mutable.Map[String, mutable.Set[String]]()
val friendsMap = mutable.Map[String, mutable.Set[String]]()
val profileImages = mutable.Map[String, ImageIcon]()
def main(args: Array[String]): Unit = {
javax.swing.SwingUtilities.invokeLater(new Runnable {
def run(): Unit = {
val loginFrame = new LoginFrame()
loginFrame.visible = true
}
})
}
class LoginFrame extends MainFrame {
title = "Kojo Social - Login"
resizable = false
minimumSize = new Dimension(400, 240)
centerOnScreen()
val idField = new TextField(15)
val passField = new PasswordField(15)
val loginButton = new Button("Login / Register")
val errorLabel = new Label("") { foreground = Color.RED }
contents = new BoxPanel(Orientation.Vertical) {
border = Swing.EmptyBorder(20, 20, 20, 20)
// ?????? ?????? ?? ??? ????? ????? ???
contents += new BoxPanel(Orientation.Horizontal) { contents += new Label("ID: "); contents += idField }
contents += Swing.VStrut(5)
contents += new BoxPanel(Orientation.Horizontal) { contents += new Label("Pass: "); contents += passField }
contents += Swing.VStrut(15)
contents += loginButton
contents += Swing.VStrut(10)
contents += errorLabel
}
listenTo(loginButton)
reactions += {
case ButtonClicked(`loginButton`) =>
val id = idField.text.trim
val pass = new String(passField.peer.getPassword).trim
if (id.nonEmpty && pass.nonEmpty) {
if (registeredUsers.contains(id) && registeredUsers(id) != pass) {
errorLabel.text = "Incorrect Password!"
} else {
registeredUsers(id) = pass
onlineUsers += id
val dashboard = new ThreeColumnDashboard(id)
dashboard.visible = true
this.dispose()
}
} else {
errorLabel.text = "Please fill all fields!"
}
}
}
class ThreeColumnDashboard(currentUserId: String) extends MainFrame {
title = s"Kojo Social Dashboard - Logged in as: $currentUserId"
minimumSize = new Dimension(1150, 700)
centerOnScreen()
val usersListPanel = new BoxPanel(Orientation.Vertical)
val usersScroll = new ScrollPane(usersListPanel) {
preferredSize = new Dimension(250, 600)
}
def refreshOnlineUsers(): Unit = {
usersListPanel.contents.clear()
usersListPanel.contents += new Label("Active Users (Online):") { font = new Font("Arial", Font.BOLD, 13) }
usersListPanel.contents += Swing.VStrut(10)
for (user <- onlineUsers) {
val displayName = if (user == currentUserId) s"$user (You)" else user
val btn = new Button(displayName) {
horizontalAlignment = Alignment.Left
maximumSize = new Dimension(230, 30)
}
listenTo(btn)
reactions += {
case ButtonClicked(`btn`) =>
if (user != currentUserId) {
showRightColumnProfile(user)
} else {
Dialog.showMessage(usersListPanel, "This is your own profile.", "Info", Dialog.Message.Info)
}
}
usersListPanel.contents += btn
usersListPanel.contents += Swing.VStrut(5)
}
usersListPanel.revalidate()
usersListPanel.repaint()
}
val postInput = new TextField(20)
val postButton = new Button("Upload Post / Google Image URL")
val feedPanel = new BoxPanel(Orientation.Vertical)
val feedScroll = new ScrollPane(feedPanel) {
preferredSize = new Dimension(520, 600)
}
def refreshFeed(): Unit = {
feedPanel.contents.clear()
feedPanel.contents += new Label("Live Feed & Posts (Right-click to add Post):") { font = new Font("Arial", Font.BOLD, 13) }
feedPanel.contents += Swing.VStrut(10)
for ((author, content) <- postsList.reverse) {
val postBox = new BoxPanel(Orientation.Vertical) {
border = Swing.CompoundBorder(Swing.LineBorder(Color.LIGHT_GRAY), Swing.EmptyBorder(10, 10, 10, 10))
contents += new Label(s"Author: $author") { font = new Font("Arial", Font.BOLD, 12); foreground = Color.BLUE }
contents += Swing.VStrut(5)
if (content.startsWith("http") && (content.endsWith(".png") || content.endsWith(".jpg") || content.endsWith(".jpeg") || content.contains("img") || content.contains("google"))) {
try {
val imgIcon = new ImageIcon(new URL(content))
val image = imgIcon.getImage.getScaledInstance(220, 160, java.awt.Image.SCALE_SMOOTH)
contents += new Label { icon = new ImageIcon(image) }
} catch {
case _: Throwable => contents += new Label(content) { font = new Font("Arial", Font.PLAIN, 12) }
}
} else {
contents += new Label(content) { font = new Font("Arial", Font.PLAIN, 12) }
}
}
feedPanel.contents += postBox
feedPanel.contents += Swing.VStrut(10)
}
feedPanel.revalidate()
feedPanel.repaint()
}
feedPanel.peer.addMouseListener(new java.awt.event.MouseAdapter {
override def mousePressed(e: MouseEvent): Unit = {
if (e.isPopupTrigger || e.getButton() == MouseEvent.BUTTON3) {
val urlInput = Dialog.showInput(feedPanel, "Paste Google Image URL or Text for Post:", "Add New Post", Dialog.Message.Question, null, Nil, "")
urlInput match {
case Some(text: String) if text.trim.nonEmpty =>
postsList += ((currentUserId, text.trim))
refreshFeed()
case _ =>
}
}
}
})
val rightPanel = new BoxPanel(Orientation.Vertical) {
border = Swing.EmptyBorder(10, 10, 10, 10)
contents += new Label("Click a user on the left to view profile") {
font = new Font("Arial", Font.ITALIC, 12)
}
}
val rightScroll = new ScrollPane(rightPanel) {
preferredSize = new Dimension(320, 600)
}
def showRightColumnProfile(targetUser: String): Unit = {
rightPanel.contents.clear()
rightPanel.contents += new Label(s"Profile: $targetUser") { font = new Font("Arial", Font.BOLD, 14) }
rightPanel.contents += Swing.VStrut(10)
val circlePanel = new Panel {
preferredSize = new Dimension(150, 150)
maximumSize = new Dimension(150, 150)
override def paintComponent(g: Graphics2D): Unit = {
super.paintComponent(g)
g.setRenderingHint(java.awt.RenderingHints.KEY_ANTIALIASING, java.awt.RenderingHints.VALUE_ANTIALIAS_ON)
val sizeDim = Math.min(size.width, size.height)
val x = (size.width - sizeDim) / 2
val y = (size.height - sizeDim) / 2
g.setColor(new Color(41, 128, 185))
g.fillOval(x, y, sizeDim, sizeDim)
profileImages.get(targetUser) match {
case Some(icon) =>
val img = icon.getImage.getScaledInstance(sizeDim, sizeDim, java.awt.Image.SCALE_SMOOTH)
g.drawImage(img, x, y, null)
case None =>
g.setColor(Color.WHITE)
g.setFont(new Font("Arial", Font.BOLD, 14))
val metrics = g.getFontMetrics
val txt = targetUser
g.drawString(txt, x + (sizeDim - metrics.stringWidth(txt)) / 2, y + sizeDim / 2)
}
g.setColor(Color.DARK_GRAY)
g.drawOval(x, y, sizeDim, sizeDim)
}
peer.addMouseListener(new java.awt.event.MouseAdapter {
override def mousePressed(e: MouseEvent): Unit = {
if (e.isPopupTrigger || e.getButton() == MouseEvent.BUTTON3) {
val urlOpt = Dialog.showInput(rightPanel, "Right-Click: Paste Google Image URL for Profile Photo:", "Set Profile Photo", Dialog.Message.Question, null, Nil, "")
urlOpt match {
case Some(urlStr: String) if urlStr.trim.nonEmpty =>
try {
val icon = new ImageIcon(new URL(urlStr.trim))
profileImages(targetUser) = icon
repaint()
Dialog.showMessage(rightPanel, "Profile photo updated successfully!")
} catch {
case _: Throwable => Dialog.showMessage(rightPanel, "Invalid Image URL!", "Error", Dialog.Message.Error)
}
case _ =>
}
} else if (e.getButton() == MouseEvent.BUTTON1) {
showFullProfileDetails(targetUser)
}
}
})
}
rightPanel.contents += circlePanel
rightPanel.contents += new Label("(Left-click circle to open options & Chat)") { font = new Font("Arial", Font.ITALIC, 10); foreground = Color.GRAY }
rightPanel.contents += new Label("(Right-click circle to set Google Photo)") { font = new Font("Arial", Font.ITALIC, 10); foreground = Color.GRAY }
rightPanel.revalidate()
rightPanel.repaint()
}
def showFullProfileDetails(targetUser: String): Unit = {
rightPanel.contents.clear()
rightPanel.contents += new Label(s"Profile: $targetUser") { font = new Font("Arial", Font.BOLD, 14) }
rightPanel.contents += Swing.VStrut(10)
val circlePanel = new Panel {
preferredSize = new Dimension(150, 150)
maximumSize = new Dimension(150, 150)
override def paintComponent(g: Graphics2D): Unit = {
super.paintComponent(g)
g.setRenderingHint(java.awt.RenderingHints.KEY_ANTIALIASING, java.awt.RenderingHints.VALUE_ANTIALIAS_ON)
val sizeDim = Math.min(size.width, size.height)
val x = (size.width - sizeDim) / 2
val y = (size.height - sizeDim) / 2
g.setColor(new Color(41, 128, 185))
g.fillOval(x, y, sizeDim, sizeDim)
profileImages.get(targetUser) match {
case Some(icon) =>
val img = icon.getImage.getScaledInstance(sizeDim, sizeDim, java.awt.Image.SCALE_SMOOTH)
g.drawImage(img, x, y, null)
case None =>
g.setColor(Color.WHITE)
g.setFont(new Font("Arial", Font.BOLD, 14))
val metrics = g.getFontMetrics
val txt = targetUser
g.drawString(txt, x + (sizeDim - metrics.stringWidth(txt)) / 2, y + sizeDim / 2)
}
g.setColor(Color.DARK_GRAY)
g.drawOval(x, y, sizeDim, sizeDim)
}
peer.addMouseListener(new java.awt.event.MouseAdapter {
override def mousePressed(e: MouseEvent): Unit = {
if (e.isPopupTrigger || e.getButton() == MouseEvent.BUTTON3) {
val urlOpt = Dialog.showInput(rightPanel, "Right-Click: Paste Google Image URL for Profile Photo:", "Set Profile Photo", Dialog.Message.Question, null, Nil, "")
urlOpt match {
case Some(urlStr: String) if urlStr.trim.nonEmpty =>
try {
val icon = new ImageIcon(new URL(urlStr.trim))
profileImages(targetUser) = icon
repaint()
Dialog.showMessage(rightPanel, "Profile photo updated successfully!")
} catch {
case _: Throwable => Dialog.showMessage(rightPanel, "Invalid Image URL!", "Error", Dialog.Message.Error)
}
case _ =>
}
}
}
})
}
rightPanel.contents += circlePanel
rightPanel.contents += Swing.VStrut(15)
val reqButton = new Button()
val chatButton = new Button("Open Live Chat") { enabled = false }
val areFriends = friendsMap.getOrElse(currentUserId, mutable.Set()).contains(targetUser)
val sentReqs = friendRequests.getOrElse(targetUser, mutable.Set())
if (areFriends) {
reqButton.text = "Connected (Friends)"
reqButton.enabled = false
chatButton.enabled = true
} else if (sentReqs.contains(currentUserId)) {
reqButton.text = "Request Sent"
reqButton.enabled = false
} else {
reqButton.text = "Send Friend Request"
reqButton.enabled = true
}
listenTo(reqButton)
listenTo(chatButton)
reactions += {
case ButtonClicked(`reqButton`) =>
friendRequests.getOrElseUpdate(targetUser, mutable.Set()) += currentUserId
reqButton.text = "Request Sent"
reqButton.enabled = false
Dialog.showMessage(rightPanel, s"Friend request sent to $targetUser!")
case ButtonClicked(`chatButton`) =>
val chatWindow = new LiveChatWindow(currentUserId, targetUser)
chatWindow.visible = true
}
rightPanel.contents += reqButton
rightPanel.contents += Swing.VStrut(10)
rightPanel.contents += chatButton
rightPanel.contents += Swing.VStrut(20)
rightPanel.contents += new Label("Incoming Requests:") { font = new Font("Arial", Font.BOLD, 12) }
val myReqs = friendRequests.getOrElse(currentUserId, mutable.Set())
for (requester <- myReqs) {
val reqBox = new BoxPanel(Orientation.Horizontal) {
contents += new Label(requester)
val acceptBtn = new Button("Accept")
val rejectBtn = new Button("Reject")
listenTo(acceptBtn, rejectBtn)
reactions += {
case ButtonClicked(`acceptBtn`) =>
myReqs -= requester
friendsMap.getOrElseUpdate(currentUserId, mutable.Set()) += requester
friendsMap.getOrElseUpdate(requester, mutable.Set()) += currentUserId
Dialog.showMessage(rightPanel, s"You are now friends with $requester!")
showFullProfileDetails(targetUser)
case ButtonClicked(`rejectBtn`) =>
myReqs -= requester
showFullProfileDetails(targetUser)
}
contents += acceptBtn
contents += rejectBtn
}
rightPanel.contents += reqBox
}
rightPanel.revalidate()
rightPanel.repaint()
}
contents = new BoxPanel(Orientation.Horizontal) {
contents += usersScroll
contents += new Separator(Orientation.Vertical)
contents += new BoxPanel(Orientation.Vertical) {
border = Swing.EmptyBorder(10, 10, 10, 10)
contents += new BoxPanel(Orientation.Horizontal) {
contents += new Label("Post / Image URL: ")
contents += postInput
contents += postButton
}
contents += Swing.VStrut(10)
contents += feedScroll
}
contents += new Separator(Orientation.Vertical)
contents += rightScroll
}
listenTo(postButton)
reactions += {
case ButtonClicked(`postButton`) =>
val content = postInput.text.trim
if (content.nonEmpty) {
postsList += ((currentUserId, content))
postInput.text = ""
refreshFeed()
}
}
refreshOnlineUsers()
refreshFeed()
}
class LiveChatWindow(userA: String, userB: String) extends MainFrame {
title = s"Live Chat: $userA & $userB"
minimumSize = new Dimension(400, 350)
centerOnScreen()
val chatArea = new TextArea(12, 30) { editable = false }
val msgField = new TextField(20)
val sendBtn = new Button("Send")
contents = new BoxPanel(Orientation.Vertical) {
border = Swing.EmptyBorder(10, 10, 10, 10)
contents += new ScrollPane(chatArea)
contents += Swing.VStrut(10)
contents += new BoxPanel(Orientation.Horizontal) {
contents += msgField
contents += sendBtn
}
}
listenTo(sendBtn)
reactions += {
case ButtonClicked(`sendBtn`) =>
val text = msgField.text.trim
if (text.nonEmpty) {
chatArea.append(s"$userA:$text\n")
msgField.text = ""
}
}
}
}
KojoMultiPCApp.main(Array())