Code Sketch
bhimraj
Category: Art
import scala.swing._
import scala.swing.event._
import java.awt.Color
import java.awt.Graphics2D
import java.awt.Font
import java.awt.event.MouseEvent
import scala.collection.mutable
object KojoSocialApp {
// Global databases (Local Memory)
private val registeredUsers = mutable.Map[String, String]()
// Follow system databases
private val followersMap = mutable.Map[String, mutable.Set[String]]()
private val followingMap = mutable.Map[String, mutable.Set[String]]()
private val followRequests = mutable.Map[String, mutable.Set[String]]()
// Chat messages storage
private val chatHistories = mutable.Map[String, mutable.ListBuffer[ChatMessage]]()
case class ChatMessage(sender: String, text: String)
def main(args: Array[String]): Unit = {
// Default Dummy Users Testing ke liye
registeredUsers("user1") = "Rahul123"
registeredUsers("user2") = "Amit99"
registeredUsers("user3") = "Priya2026"
javax.swing.SwingUtilities.invokeLater(new Runnable {
def run(): Unit = {
val startFrame = new StartupSearchLoginFrame()
startFrame.visible = true
}
})
}
// 1. STARTUP SEARCH & LOGIN FRAME
class StartupSearchLoginFrame extends MainFrame {
title = "Kojo Social App - Login & Register"
resizable = false
minimumSize = new Dimension(440, 330)
centerOnScreen()
val searchIdField = new TextField(10)
val searchPasswordField = new PasswordField(10)
val searchLoginButton = new Button("Login")
val newIdField = new TextField(10)
val newPasswordField = new PasswordField(10)
val createAccountButton = new Button("Register New Account")
val messageLabel = new Label("Enter your ID & Password to login or register.") {
foreground = new Color(0, 100, 0)
font = new Font("Arial", Font.BOLD, 12)
}
contents = new BoxPanel(Orientation.Vertical) {
border = Swing.EmptyBorder(20, 20, 20, 20)
contents += new Label("=== Welcome to Kojo Social ===") { font = new Font("Arial", Font.BOLD, 15) }
contents += Swing.VStrut(15)
contents += new Label("Already have an ID? Login here:")
contents += Swing.VStrut(5)
contents += new BoxPanel(Orientation.Horizontal) {
contents += new Label("ID: ")
contents += searchIdField
contents += Swing.HStrut(5)
contents += new Label("Pass: ")
contents += searchPasswordField
contents += Swing.HStrut(10)
contents += searchLoginButton
}
contents += Swing.VStrut(15)
contents += new Separator()
contents += Swing.VStrut(15)
contents += new Label("New User? Register with ID & Password:")
contents += Swing.VStrut(8)
contents += new BoxPanel(Orientation.Horizontal) {
contents += new Label("ID: ")
contents += newIdField
}
contents += Swing.VStrut(5)
contents += new BoxPanel(Orientation.Horizontal) {
contents += new Label("Pass: ")
contents += newPasswordField
}
contents += Swing.VStrut(12)
contents += createAccountButton
contents += Swing.VStrut(10)
contents += messageLabel
}
listenTo(searchLoginButton)
listenTo(createAccountButton)
reactions += {
case ButtonClicked(`searchLoginButton`) =>
val idToSearch = searchIdField.text.trim
val enteredPass = new String(searchPasswordField.peer.getPassword).trim
if (idToSearch.isEmpty || enteredPass.isEmpty) {
messageLabel.text = "Please enter both ID and Password!"
messageLabel.foreground = Color.RED
} else if (registeredUsers.contains(idToSearch)) {
val correctPass = registeredUsers(idToSearch)
if (correctPass == enteredPass) {
val dashboard = new FullScreenDashboard(idToSearch)
dashboard.peer.setExtendedState(java.awt.Frame.MAXIMIZED_BOTH)
dashboard.visible = true
this.dispose()
} else {
messageLabel.text = "Incorrect Password!"
messageLabel.foreground = Color.RED
}
} else {
messageLabel.text = "ID not found! Please register below."
messageLabel.foreground = Color.RED
}
case ButtonClicked(`createAccountButton`) =>
val id = newIdField.text.trim
val pass = new String(newPasswordField.peer.getPassword).trim
if (id.isEmpty || pass.isEmpty) {
messageLabel.text = "Enter both ID and Password to register!"
messageLabel.foreground = Color.RED
} else if (registeredUsers.contains(id)) {
messageLabel.text = "This ID already exists! Try logging in above."
messageLabel.foreground = Color.RED
} else {
registeredUsers(id) = pass
val dashboard = new FullScreenDashboard(id)
dashboard.peer.setExtendedState(java.awt.Frame.MAXIMIZED_BOTH)
dashboard.visible = true
this.dispose()
}
}
}
// 2. FULL SCREEN DASHBOARD
class FullScreenDashboard(currentUserId: String) extends MainFrame {
title = "Kojo Application - Welcome ID: " + currentUserId
minimumSize = new Dimension(1024, 728)
val backButton = new Button("<-- Back")
val searchField = new TextField(20)
val searchButton = new Button("Search ID")
val searchResultLabel = new Label("Search registered users here...") {
foreground = Color.BLUE
font = new Font("Arial", Font.BOLD, 14)
}
val limButton = new Button("LIM") {
font = new Font("Arial", Font.BOLD, 14)
foreground = new Color(41, 128, 185)
tooltip = "Click to view logged-in user name/ID"
}
val topPanel = new BoxPanel(Orientation.Horizontal) {
border = Swing.EmptyBorder(15, 20, 15, 20)
contents += backButton
contents += Swing.HStrut(15)
contents += new Label("Search User ID: ") { font = new Font("Arial", Font.BOLD, 14) }
contents += Swing.HStrut(10)
contents += searchField
contents += Swing.HStrut(10)
contents += searchButton
contents += Swing.HStrut(20)
contents += searchResultLabel
contents += Swing.HGlue
contents += limButton
}
val drawingCanvas = new Panel {
background = new Color(245, 247, 250)
var circleCenterX = 0
var circleCenterY = 0
var circleRadius = 0
override def paintComponent(g: Graphics2D): Unit = {
super.paintComponent(g)
g.setRenderingHint(java.awt.RenderingHints.KEY_ANTIALIASING, java.awt.RenderingHints.VALUE_ANTIALIAS_ON)
val w = size.width
val h = size.height
val diameter = (Math.min(w, h) * 0.70).toInt
circleRadius = diameter / 2
circleCenterX = w / 2
circleCenterY = h / 2
val circleX = circleCenterX - circleRadius
val circleY = circleCenterY - circleRadius
// Circle Shadow
g.setColor(new Color(200, 200, 200, 120))
g.fillOval(circleX + 10, circleY + 10, diameter, diameter)
// Main Circle
g.setColor(new Color(41, 128, 185))
g.fillOval(circleX, circleY, diameter, diameter)
// Circle Border
g.setColor(new Color(21, 67, 96))
g.setStroke(new java.awt.BasicStroke(5))
g.drawOval(circleX, circleY, diameter, diameter)
// Text inside Circle
g.setColor(Color.WHITE)
g.setFont(new Font("Arial", Font.BOLD, (diameter * 0.11).toInt))
val idText = "ID: " + currentUserId
val metrics = g.getFontMetrics
val idX = circleCenterX - (metrics.stringWidth(idText) / 2)
val idY = circleCenterY + 10
g.drawString(idText, idX, idY)
// Hint text
g.setColor(Color.DARK_GRAY)
g.setFont(new Font("Arial", Font.BOLD, 16))
val hintText = "( Click anywhere on this big circle to open your profile )"
val hintMetrics = g.getFontMetrics
g.drawString(hintText, circleCenterX - (hintMetrics.stringWidth(hintText) / 2), circleY + diameter + 30)
}
peer.addMouseListener(new java.awt.event.MouseAdapter {
override def mouseClicked(e: MouseEvent): Unit = {
val dx = e.getX - circleCenterX
val dy = e.getY - circleCenterY
if (dx * dx + dy * dy <= circleRadius * circleRadius) {
val profileWin = new ProfileFrame(currentUserId, currentUserId)
profileWin.visible = true
}
}
})
}
val logoutButton = new Button("Logout") {
foreground = Color.RED
font = new Font("Arial", Font.BOLD, 12)
}
val bottomPanel = new BoxPanel(Orientation.Horizontal) {
border = Swing.EmptyBorder(10, 20, 15, 20)
contents += Swing.HGlue
contents += logoutButton
}
contents = new BorderPanel {
layout(topPanel) = BorderPanel.Position.North
layout(drawingCanvas) = BorderPanel.Position.Center
layout(bottomPanel) = BorderPanel.Position.South
}
listenTo(backButton)
listenTo(searchButton)
listenTo(limButton)
listenTo(logoutButton)
listenTo(searchField.keys)
reactions += {
case ButtonClicked(`backButton`) =>
val loginScreen = new StartupSearchLoginFrame()
loginScreen.visible = true
this.dispose()
case ButtonClicked(`searchButton`) =>
performSearch()
case ButtonClicked(`limButton`) =>
Dialog.showMessage(this, s"Currently Logged-in User ID: $currentUserId", "Logged-In Member (LIM)", Dialog.Message.Info)
case ButtonClicked(`logoutButton`) =>
val confirm = Dialog.showConfirmation(this, "Are you sure you want to logout?", "Confirm Logout", Dialog.Options.YesNo, Dialog.Message.Question)
if (confirm == Dialog.Result.Yes) {
val loginScreen = new StartupSearchLoginFrame()
loginScreen.visible = true
this.dispose()
}
case KeyPressed(_, Key.Enter, _, _) =>
performSearch()
}
def performSearch(): Unit = {
val queryId = searchField.text.trim
if (queryId.nonEmpty) {
if (registeredUsers.contains(queryId)) {
searchResultLabel.text = s"Found ID: $queryId. Opening profile..."
searchResultLabel.foreground = new Color(39, 174, 96)
val externalProfile = new ProfileFrame(queryId, currentUserId)
externalProfile.visible = true
} else {
searchResultLabel.text = "No registered user found with this ID"
searchResultLabel.foreground = Color.RED
}
} else {
searchResultLabel.text = "Please enter an ID to search!"
searchResultLabel.foreground = Color.RED
}
}
}
// 3. PROFILE WINDOW
class ProfileFrame(profileUserId: String, viewerUserId: String) extends MainFrame {
title = s"Profile - ID: $profileUserId"
minimumSize = new Dimension(450, 350)
centerOnScreen()
val profileBackBtn = new Button("<-- Back")
val captionLabel = new Label(s"User Profile | ID: $profileUserId") {
font = new Font("Arial", Font.BOLD, 15)
}
val followerButton = new Button("Follower")
val followingButton = new Button("Following")
val requestButton = new Button("Request")
val chatButton = new Button("Chat")
val statusMessage = new Label("") {
font = new Font("Arial", Font.BOLD, 13)
foreground = new Color(0, 128, 0)
}
def updateButtonStates(): Unit = {
if (profileUserId == viewerUserId) {
requestButton.text = "View Requests"
chatButton.enabled = false
} else {
val isFollowing = followingMap.getOrElse(viewerUserId, mutable.Set()).contains(profileUserId)
val reqs = followRequests.getOrElse(profileUserId, mutable.Set())
if (isFollowing) {
requestButton.text = "Connected"
requestButton.enabled = false
chatButton.enabled = true
} else if (reqs.contains(viewerUserId)) {
requestButton.text = "Request Sent"
requestButton.enabled = false
chatButton.enabled = false
} else {
requestButton.text = "Send Request"
requestButton.enabled = true
chatButton.enabled = false
}
}
}
updateButtonStates()
contents = new BoxPanel(Orientation.Vertical) {
border = Swing.EmptyBorder(20, 20, 20, 20)
contents += new BoxPanel(Orientation.Horizontal) {
contents += profileBackBtn
contents += Swing.HStrut(15)
contents += captionLabel
}
contents += Swing.VStrut(25)
contents += new BoxPanel(Orientation.Horizontal) {
contents += followerButton
contents += Swing.HStrut(10)
contents += followingButton
contents += Swing.HStrut(10)
contents += requestButton
contents += Swing.HStrut(10)
contents += chatButton
}
contents += Swing.VStrut(25)
contents += statusMessage
}
listenTo(profileBackBtn)
listenTo(followerButton)
listenTo(followingButton)
listenTo(requestButton)
listenTo(chatButton)
reactions += {
case ButtonClicked(`profileBackBtn`) =>
this.close()
case ButtonClicked(`followerButton`) =>
val fWin = new ListViewerFrame(s"Followers of $profileUserId", followersMap.getOrElse(profileUserId, mutable.Set()).toSet)
fWin.visible = true
case ButtonClicked(`followingButton`) =>
val fWin = new ListViewerFrame(s"Following of $profileUserId", followingMap.getOrElse(profileUserId, mutable.Set()).toSet)
fWin.visible = true
case ButtonClicked(`requestButton`) =>
if (profileUserId == viewerUserId) {
val reqWin = new FollowRequestsDialog(viewerUserId)
reqWin.visible = true
} else {
val reqs = followRequests.getOrElseUpdate(profileUserId, mutable.Set())
if (!reqs.contains(viewerUserId)) {
reqs += viewerUserId
statusMessage.text = "Follow request sent successfully!"
statusMessage.foreground = new Color(39, 174, 96)
updateButtonStates()
}
}
case ButtonClicked(`chatButton`) =>
val chatWin = new LiveChatFrame(viewerUserId, profileUserId)
chatWin.visible = true
}
}
class ListViewerFrame(titleText: String, items: Set[String]) extends MainFrame {
title = titleText
minimumSize = new Dimension(300, 250)
centerOnScreen()
val listPanel = new BoxPanel(Orientation.Vertical) {
border = Swing.EmptyBorder(10, 10, 10, 10)
if (items.isEmpty) {
contents += new Label("No users found.")
} else {
for (item <- items) {
contents += new Label(s"- $item") { font = new Font("Arial", Font.PLAIN, 14) }
contents += Swing.VStrut(5)
}
}
}
contents = new ScrollPane(listPanel)
}
// 4. FOLLOW REQUESTS MANAGEMENT DIALOG
class FollowRequestsDialog(currentUserId: String) extends MainFrame {
title = "Manage Follow Requests"
minimumSize = new Dimension(400, 300)
centerOnScreen()
val requestsPanel = new BoxPanel(Orientation.Vertical) {
border = Swing.EmptyBorder(10, 10, 10, 10)
}
val scroll = new ScrollPane(requestsPanel)
def loadRequests(): Unit = {
requestsPanel.contents.clear()
val reqs = followRequests.getOrElse(currentUserId, mutable.Set())
if (reqs.isEmpty) {
requestsPanel.contents += new Label("No pending follow requests.") {
font = new Font("Arial", Font.BOLD, 13)
}
} else {
for (requester <- reqs) {
val row = new BoxPanel(Orientation.Horizontal) {
border = Swing.EmptyBorder(5, 5, 5, 5)
contents += new Label(s"User ID: $requester") { font = new Font("Arial", Font.BOLD, 13) }
contents += Swing.HStrut(20)
val acceptBtn = new Button("Accept")
val rejectBtn = new Button("Reject")
listenTo(acceptBtn)
listenTo(rejectBtn)
reactions += {
case ButtonClicked(`acceptBtn`) =>
reqs -= requester
followersMap.getOrElseUpdate(currentUserId, mutable.Set()) += requester
followingMap.getOrElseUpdate(requester, mutable.Set()) += currentUserId
loadRequests()
case ButtonClicked(`rejectBtn`) =>
reqs -= requester
loadRequests()
}
contents += acceptBtn
contents += Swing.HStrut(5)
contents += rejectBtn
}
requestsPanel.contents += row
requestsPanel.contents += Swing.VStrut(5)
}
}
requestsPanel.revalidate()
requestsPanel.repaint()
}
loadRequests()
val closeBtn = new Button("Close")
contents = new BoxPanel(Orientation.Vertical) {
border = Swing.EmptyBorder(15, 15, 15, 15)
contents += new Label("Pending Requests:") { font = new Font("Arial", Font.BOLD, 15) }
contents += Swing.VStrut(10)
contents += scroll
contents += Swing.VStrut(15)
contents += closeBtn
}
listenTo(closeBtn)
reactions += {
case ButtonClicked(`closeBtn`) => this.close()
}
}
// 5. LIVE CHAT WINDOW
class LiveChatFrame(userA: String, userB: String) extends MainFrame {
private val chatKey = if (userA < userB) s"$userA-$userB" else s"$userB-$userA"
title = s"Live Chat: $userA & $userB"
minimumSize = new Dimension(450, 450)
centerOnScreen()
val chatArea = new TextArea(15, 35) {
editable = false
lineWrap = true
wordWrap = true
font = new Font("Arial", Font.PLAIN, 13)
}
val messageInput = new TextField(25)
val sendButton = new Button("Send")
def refreshChat(): Unit = {
val messages = chatHistories.getOrElse(chatKey, mutable.ListBuffer())
val sb = new StringBuilder
for (msg <- messages) {
sb.append(s"[${msg.sender}]:${msg.text}\n")
}
chatArea.text = sb.toString()
chatArea.peer.setCaretPosition(chatArea.text.length)
}
refreshChat()
contents = new BoxPanel(Orientation.Vertical) {
border = Swing.EmptyBorder(15, 15, 15, 15)
contents += new Label(s"Chatting with: $userB") {
font = new Font("Arial", Font.BOLD, 14)
}
contents += Swing.VStrut(10)
contents += new ScrollPane(chatArea)
contents += Swing.VStrut(10)
contents += new BoxPanel(Orientation.Horizontal) {
contents += messageInput
contents += Swing.HStrut(10)
contents += sendButton
}
}
listenTo(sendButton)
listenTo(messageInput.keys)
reactions += {
case ButtonClicked(`sendButton`) =>
sendMessage()
case KeyPressed(_, Key.Enter, _, _) =>
sendMessage()
}
def sendMessage(): Unit = {
val text = messageInput.text.trim
if (text.nonEmpty) {
val list = chatHistories.getOrElseUpdate(chatKey, mutable.ListBuffer())
list += ChatMessage(userA, text)
messageInput.text = ""
refreshChat()
}
}
}
}
// App ko run karne ke liye:
KojoSocialApp.main(Array())