Jigs_Desktop_Client.GUI.FXMLDocumentController.java Source code

Java tutorial

Introduction

Here is the source code for Jigs_Desktop_Client.GUI.FXMLDocumentController.java

Source

/*
 * Copyright (C) 2017 Anwar
 *
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 */
package Jigs_Desktop_Client.GUI;

import Jigs_Desktop_Client.resources.Message;
import Jigs_Desktop_Client.resources.User;
import Jigs_Desktop_Client.service.Jigs_client;
import Jigs_Desktop_Client.service.SyncMessages;
import Jigs_Desktop_Client.service.SyncUserStatus;
import java.io.IOException;
import java.math.BigInteger;
import java.net.URISyntaxException;
import java.net.URL;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.util.ResourceBundle;
import java.util.logging.Level;
import java.util.logging.Logger;
import javafx.collections.FXCollections;
import javafx.collections.ObservableList;
import javafx.event.ActionEvent;
import javafx.event.EventHandler;
import javafx.fxml.FXML;
import javafx.fxml.Initializable;
import javafx.scene.control.Button;
import javafx.scene.control.Label;
import javafx.scene.control.ListCell;
import javafx.scene.control.ListView;
import javafx.scene.control.PasswordField;
import javafx.scene.control.Tab;
import javafx.scene.control.TabPane;
import javafx.scene.control.TextArea;
import javafx.scene.control.TextField;
import javafx.scene.image.Image;
import javafx.scene.image.ImageView;
import javafx.scene.input.KeyCode;
import javafx.scene.input.KeyEvent;
import javafx.scene.input.MouseEvent;
import javafx.scene.layout.AnchorPane;
import javafx.scene.layout.Background;
import javafx.scene.media.Media;
import javafx.scene.media.MediaPlayer;
import javafx.scene.paint.Color;
import javafx.scene.shape.Circle;
import javafx.stage.Stage;
import javafx.util.Callback;
import org.apache.commons.lang3.text.WordUtils;

/**
 *
 * @author Anwar
 */
public class FXMLDocumentController implements Initializable, Runnable {

    private String to_user;
    private static String from_user;
    private final Jigs_client jc;
    private final ObservableList<String> messages;
    private final ObservableList<String> circles;
    private final ObservableList<UserStatus> users_available;
    Thread syncmessageThread;
    Thread syncUserStatusThread;

    @FXML
    private AnchorPane main_panel;

    @FXML
    private TabPane main_tab_pane;

    // First tab

    @FXML
    private TextField user_name;

    @FXML
    private PasswordField password;

    @FXML
    private Button btn_login;

    @FXML
    private Button btn_logout;

    @FXML
    private Button btn_exit;

    @FXML
    private Label login_status;

    // Second tab

    @FXML
    private ImageView spin_earth_image;

    @FXML
    private Tab my_circle_tab;

    @FXML
    private Button connect_selected_user;

    @FXML
    private ListView<UserStatus> my_circle_list;

    @FXML
    private Label selected_user;

    @FXML
    private TextField circle_username_search;

    @FXML
    private Button btn_circle_user_search;

    // Third tab
    @FXML
    private Tab message_tab;

    @FXML
    private TextField search_user;

    @FXML
    private Button btn_disconnect;

    @FXML
    private Circle connection_circle;

    @FXML
    private Label search_user_result;

    @FXML
    private ListView<String> messages_list;

    @FXML
    private TextArea text_message;

    @FXML
    private Button btn_send;

    // Constructor
    public FXMLDocumentController() {
        jc = new Jigs_client();
        messages = FXCollections.observableArrayList();
        circles = FXCollections.observableArrayList();
        users_available = FXCollections.observableArrayList();
    }

    @FXML
    private void searchUser(ActionEvent event) {

    }

    @FXML
    private void allUsers(ActionEvent event) {

    }

    @FXML
    private void connectUser(ActionEvent event) {
        String user_to_search = this.to_user;
        System.out.println("Connect is pressed");
        System.out.println("Called Connect user: " + to_user);
        this.connectToUser(user_to_search);
        this.btn_disconnect.setDisable(false);
    }

    private void connectToUser(String user_to_search) {
        if (user_to_search.equals(""))
            user_to_search = this.to_user;
        try {
            System.out.println("Searching for: " + user_to_search);
            if (jc.findUser(user_to_search)) {
                String to_user_status = "offline";
                this.to_user = user_to_search;
                for (UserStatus us : this.users_available) {
                    if (us.getUsername().equalsIgnoreCase(user_to_search))
                        to_user_status = us.getStatus();
                }
                if (to_user_status.equals("online")) {
                    this.connection_circle.setFill(Color.LIGHTGREEN);
                    search_user_result.setText("Connected to @" + user_to_search);
                    this.selected_user.setText("Connected to @" + user_to_search);
                    try {
                        this.spin_earth_image.setImage(new Image(
                                getClass().getResource("resources/spin_earth_bright.gif").toURI().toString()));
                    } catch (URISyntaxException ex) {
                        this.alert("resources/app_error.mp3");
                    }
                } else {
                    this.connection_circle.setFill(Color.YELLOW);
                    search_user_result.setText("Offline messaging @" + user_to_search);
                    this.selected_user.setText("Sending offline messages @" + user_to_search);
                }
                this.btn_send.setDisable(false);
                this.alert("resources/app_user_connected.mp3");
                main_tab_pane.getSelectionModel().select(2);
            } else {
                this.connection_circle.setFill(Color.RED);
                search_user_result.setText("No user found for @" + user_to_search);
                this.btn_send.setDisable(true);
                this.alert("resources/app_no_such_user.mp3");
            }
        } catch (IOException ex) {
            this.connection_circle.setFill(Color.RED);
            search_user_result.setText(ex.getMessage());
            this.btn_send.setDisable(true);
            this.alert("resources/app_error.mp3");
        }
    }

    @FXML
    private void sendMessage(ActionEvent event) {
        String message = this.text_message.getText();
        this.text_message.clear();
        if (!message.equals("")) {
            if (this.to_user != null) {
                System.out.println("Sending message: " + message + "To " + to_user + " from " + from_user);
                jc.sendMessage(new Message(new User(to_user), new User(from_user), message));
                String your_message = "You(" + this.from_user + "): " + message + "@" + to_user;
                your_message = WordUtils.wrap(your_message, 42);
                messages.add(your_message);
                this.messages_list.setItems(messages);
                this.alert("resources/send_msg.mp3");
            }
        }
        System.out.println("Send is Pressed");
    }

    @FXML
    private void authenticateUser(ActionEvent event) {
        from_user = this.user_name.getText();
        String pass_txt = this.password.getText();
        try {
            MessageDigest m = MessageDigest.getInstance("MD5");
            m.update(pass_txt.getBytes(), 0, pass_txt.length());
            pass_txt = (new BigInteger(1, m.digest()).toString(16));
        } catch (NoSuchAlgorithmException e) {
            this.login_status.setText(e.getMessage());
            this.alert("resources/app_error.mp3");
            return;
        }
        if ((from_user.equals("")) || (pass_txt.equals(""))) {
            this.login_status.setText("Username or password can't left empty!");
            this.alert("resources/app_error.mp3");
            return;
        }
        if (jc.authenticateUser(from_user, pass_txt)) {
            this.alert("resources/app_login.mp3");
            this.login_status.setText("Logged In as: @" + from_user);
            this.my_circle_tab.setDisable(false);
            message_tab.setDisable(false);
            this.btn_logout.setDisable(false);
            this.user_name.setDisable(true);
            this.password.setDisable(true);
            this.btn_login.setDisable(true);
            main_tab_pane.getSelectionModel().select(1);
            this.getMyCirclesList();
            SyncMessages sm = new SyncMessages(this.from_user, "132.148.65.148", this);
            syncmessageThread = new Thread(sm);
            syncmessageThread.start();
            SyncUserStatus sus = new SyncUserStatus("132.148.65.148", this);
            syncUserStatusThread = new Thread(sus);
            syncUserStatusThread.start();
            this.messages.clear();
            this.btn_login.setDefaultButton(false);
            this.btn_logout.setDefaultButton(true);
            this.jc.setStatus(from_user, "online");
            this.btn_disconnect.setDisable(true);
        } else {
            this.login_status.setText("Error logging as @" + from_user);
            this.alert("resources/app_error.mp3");
        }
    }

    @FXML
    private void logout() {
        this.alert("resources/app_logout.mp3");
        this.user_name.setText("");
        this.user_name.setDisable(false);
        this.password.setText("");
        this.password.setDisable(false);
        this.btn_login.setDisable(false);
        this.btn_logout.setDisable(true);
        this.message_tab.setDisable(true);
        if (syncmessageThread.isAlive())
            syncmessageThread.stop();
        if (syncUserStatusThread.isAlive())
            syncUserStatusThread.stop();
        this.login_status.setText("");
        this.my_circle_tab.setDisable(true);
        this.btn_login.setDefaultButton(true);
        this.circles.clear();
        this.users_available.clear();
        this.jc.setStatus(from_user, "offline");
    }

    public void updateMessagesList(String message) {
        message = WordUtils.wrap(message, 42);
        messages.add(message);
        if (!message.contains("No")) {
            this.alert("resources/app_new_message.mp3");
            Stage stage = (Stage) this.main_panel.getScene().getWindow();
            if (stage.isIconified()) {
                try {
                    stage.getIcons().setAll(new Image(
                            getClass().getResource("resources/Chat_notification.png").toURI().toString()));
                } catch (URISyntaxException ex) {
                    Logger.getLogger(FXMLDocumentController.class.getName()).log(Level.SEVERE, null, ex);
                }
            }
        }
        messages_list.setItems(messages);
    }

    private void alert(String fileName) {
        Media sound;
        try {
            sound = new Media(FXMLDocumentController.class.getResource(fileName).toURI().toString());
            MediaPlayer mediaPlayer = new MediaPlayer(sound);
            mediaPlayer.play();
        } catch (URISyntaxException ex) {
            Logger.getLogger(FXMLDocumentController.class.getName()).log(Level.SEVERE, null, ex);
        }
    }

    @Override
    public void initialize(URL url, ResourceBundle rb) {
        this.alert("resources/app_launch.mp3");
        this.user_name.requestFocus();
        this.btn_logout.setDisable(true);
        this.jc.setStatus(from_user, "online");
        this.my_circle_list.setCellFactory(new Callback<ListView<UserStatus>, ListCell<UserStatus>>() {
            @Override
            public ListCell<UserStatus> call(ListView<UserStatus> userObj) {
                ListCell<UserStatus> cell = new ListCell<UserStatus>() {
                    @Override
                    protected void updateItem(UserStatus usrObj, boolean btnl) {
                        super.updateItem(usrObj, btnl);
                        if (usrObj != null) {
                            String filename = usrObj.getStatus();
                            if (filename == null || filename.equals("") || filename.equals("null"))
                                filename = "offline";
                            else
                                System.out.println(filename);
                            Image img = new Image(
                                    getClass().getResource("resources/" + filename + ".png").toExternalForm());
                            ImageView imv = new ImageView(img);
                            setGraphic(imv);
                            setText(usrObj.getUsername());
                        }
                    }
                };
                return cell;
            }
        });
        this.main_panel.setBackground(Background.EMPTY);
        this.text_message.setOnKeyPressed(new EventHandler<KeyEvent>() {
            @Override
            public void handle(KeyEvent keyEvent) {
                if (keyEvent.getCode() == KeyCode.ENTER) {
                    sendMessage(null);
                    keyEvent.consume();
                }
            }
        });
    }

    @FXML
    public void getMyCirclesList() {
        System.out.println("Getting all users");
        this.users_available.clear();
        String allUsers[];
        try {
            allUsers = this.jc.getMyCircles();
            for (String user : allUsers) {
                String[] user_info = user.split(":");
                users_available.add(new UserStatus(user_info[0], user_info[1]));
            }
        } catch (IOException ex) {
            users_available.add(new UserStatus("Unable to fetch users!", "offline"));
            users_available.add(new UserStatus(ex.getMessage(), "offline"));
        }
        users_available.add(new UserStatus("DemoOfflineUser1", "offline"));
        this.my_circle_list.setItems(this.users_available);
    }

    @FXML
    private void showSelectedUser(MouseEvent event) {
        UserStatus usr = my_circle_list.getSelectionModel().getSelectedItem();
        if (usr == null)
            return;
        System.out.println("clicked on " + usr.getUsername());
        if (usr.getStatus().equalsIgnoreCase("online")) {
            this.selected_user.setText("Connect to @" + usr.getUsername() + "?");
            this.connect_selected_user.setText("Connect");
        } else {
            this.selected_user.setText("Send offline message to @" + usr.getUsername() + "?");
            this.connect_selected_user.setText("Yes");
        }
        this.to_user = usr.getUsername();
    }

    @FXML
    private void exit_request(ActionEvent event) {
        Stage stage = (Stage) this.main_panel.getScene().getWindow();
        stage.setIconified(true);
        this.alert("resources/app_exit.mp3");
        this.jc.setStatus(from_user, "offline");
        System.exit(0);
    }

    @Override
    public void run() {
        throw new UnsupportedOperationException("Not supported yet."); //To change body of generated methods, choose Tools | Templates.
    }

    @FXML
    private void disconnect(ActionEvent event) {
        this.to_user = "";
        this.btn_send.setDisable(true);
        this.connection_circle.setFill(Color.RED);
        this.search_user_result.setText("No active connections!");
        this.selected_user.setText("Select to user to connect!");
        try {
            this.spin_earth_image.setImage(
                    new Image(getClass().getResource("resources/spin_earth_dark.gif").toURI().toString()));
        } catch (URISyntaxException ex) {
            this.alert("resources/app_error.mp3");
        }
        this.alert("resources/app_disconnect.mp3");
        this.btn_disconnect.setDisable(true);
    }

    public static void onClose() {
        (new Jigs_client()).setStatus(from_user, "offline");
    }
}