Merge branch 'NabilFX'

This commit is contained in:
Auriane Lartigue 2020-12-29 18:09:25 +04:00
commit 85d3994d90
70 changed files with 3803 additions and 1991 deletions

View file

@ -1,10 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<classpath>
<classpathentry kind="src" path=""/>
<classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER">
<attributes>
<attribute name="module" value="true"/>
</attributes>
</classpathentry>
<classpathentry kind="output" path="bin"/>
</classpath>

View file

@ -1 +1,37 @@
/bin/ # Created by https://www.gitignore.io/api/java,gradle
### Java ###
*.class
# BlueJ files
*.ctxt
# Mobile Tools for Java (J2ME)
.mtj.tmp/
# Package Files #
*.jar
*.war
*.ear
# virtual machine crash logs, see http://www.java.com/en/download/help/error_hotspot.xml
hs_err_pid*
### Gradle ###
.gradle
/build/
# Ignore Gradle GUI config
gradle-app.setting
# Avoid ignoring Gradle wrapper jar file (.jar files are usually ignored)
!gradle-wrapper.jar
# Cache of project
.gradletasknamecache
# # Work around https://youtrack.jetbrains.com/issue/IDEA-116898
# gradle/wrapper/gradle-wrapper.properties
# End of https://www.gitignore.io/api/java,gradle

View file

@ -1,17 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<projectDescription>
<name>Implementation</name>
<comment></comment>
<projects>
</projects>
<buildSpec>
<buildCommand>
<name>org.eclipse.jdt.core.javabuilder</name>
<arguments>
</arguments>
</buildCommand>
</buildSpec>
<natures>
<nature>org.eclipse.jdt.core.javanature</nature>
</natures>
</projectDescription>

View file

@ -1,10 +0,0 @@
eclipse.preferences.version=1
org.eclipse.jdt.core.compiler.codegen.inlineJsrBytecode=enabled
org.eclipse.jdt.core.compiler.codegen.targetPlatform=13
org.eclipse.jdt.core.compiler.compliance=13
org.eclipse.jdt.core.compiler.problem.assertIdentifier=error
org.eclipse.jdt.core.compiler.problem.enablePreviewFeatures=disabled
org.eclipse.jdt.core.compiler.problem.enumIdentifier=error
org.eclipse.jdt.core.compiler.problem.reportPreviewFeatures=warning
org.eclipse.jdt.core.compiler.release=enabled
org.eclipse.jdt.core.compiler.source=13

View file

@ -0,0 +1,3 @@
# Default ignored files
/shelf/
/workspace.xml

View file

@ -0,0 +1,6 @@
<component name="ArtifactManager">
<artifact type="jar" name="chatapp">
<output-path>$PROJECT_DIR$/out/artifacts/chatapp</output-path>
<root id="archive" name="chatapp.jar" />
</artifact>
</component>

View file

@ -0,0 +1,9 @@
<?xml version="1.0" encoding="UTF-8"?>
<module type="JAVA_MODULE" version="4">
<component name="NewModuleRootManager" inherit-compiler-output="true">
<exclude-output />
<content url="file://$MODULE_DIR$" />
<orderEntry type="inheritedJdk" />
<orderEntry type="sourceFolder" forTests="false" />
</component>
</module>

View file

@ -0,0 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="CompilerConfiguration">
<bytecodeTargetLevel target="11" />
</component>
</project>

View file

@ -0,0 +1,17 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="GradleMigrationSettings" migrationVersion="1" />
<component name="GradleSettings">
<option name="linkedExternalProjectsSettings">
<GradleProjectSettings>
<option name="distributionType" value="DEFAULT_WRAPPED" />
<option name="externalProjectPath" value="$PROJECT_DIR$" />
<option name="modules">
<set>
<option value="$PROJECT_DIR$" />
</set>
</option>
</GradleProjectSettings>
</option>
</component>
</project>

View file

@ -0,0 +1,20 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="RemoteRepositoriesConfiguration">
<remote-repository>
<option name="id" value="central" />
<option name="name" value="Maven Central repository" />
<option name="url" value="https://repo1.maven.org/maven2" />
</remote-repository>
<remote-repository>
<option name="id" value="jboss.community" />
<option name="name" value="JBoss Community repository" />
<option name="url" value="https://repository.jboss.org/nexus/content/repositories/public/" />
</remote-repository>
<remote-repository>
<option name="id" value="MavenRepo" />
<option name="name" value="MavenRepo" />
<option name="url" value="https://repo.maven.apache.org/maven2/" />
</remote-repository>
</component>
</project>

View file

@ -0,0 +1,13 @@
<component name="libraryTable">
<library name="lib">
<CLASSES>
<root url="file://$USER_HOME$/JavaFX/javafx-sdk-11.0.2/lib" />
</CLASSES>
<JAVADOC />
<SOURCES>
<root url="file://$USER_HOME$/JavaFX/javafx-sdk-11.0.2/lib" />
</SOURCES>
<jarDirectory url="file://$USER_HOME$/JavaFX/javafx-sdk-11.0.2/lib" recursive="false" />
<jarDirectory url="file://$USER_HOME$/JavaFX/javafx-sdk-11.0.2/lib" recursive="false" type="SOURCES" />
</library>
</component>

View file

@ -0,0 +1,9 @@
<component name="libraryTable">
<library name="mysql-connector-java-8.0.22">
<CLASSES>
<root url="jar://$USER_HOME$/Downloads/mysql-connector-java-8.0.22.jar!/" />
</CLASSES>
<JAVADOC />
<SOURCES />
</library>
</component>

View file

@ -0,0 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="ExternalStorageConfigurationManager" enabled="true" />
<component name="ProjectRootManager" version="2" languageLevel="JDK_11" default="false" project-jdk-name="13" project-jdk-type="JavaSDK">
<output url="file://$PROJECT_DIR$/out" />
</component>
</project>

View file

@ -0,0 +1,8 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="ProjectModuleManager">
<modules>
<module fileurl="file://$PROJECT_DIR$/.idea/modules/chatapp.iml" filepath="$PROJECT_DIR$/.idea/modules/chatapp.iml" />
</modules>
</component>
</project>

View file

@ -0,0 +1,12 @@
<?xml version="1.0" encoding="UTF-8"?>
<module external.linked.project.id="chatapp" external.linked.project.path="$MODULE_DIR$/../.." external.root.project.path="$MODULE_DIR$/../.." external.system.id="GRADLE" external.system.module.group="org.example" external.system.module.version="1.0-SNAPSHOT" type="JAVA_MODULE" version="4">
<component name="NewModuleRootManager" inherit-compiler-output="true">
<exclude-output />
<content url="file://$MODULE_DIR$/../..">
<excludeFolder url="file://$MODULE_DIR$/../../.gradle" />
<excludeFolder url="file://$MODULE_DIR$/../../build" />
</content>
<orderEntry type="inheritedJdk" />
<orderEntry type="sourceFolder" forTests="false" />
</component>
</module>

View file

@ -0,0 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="VcsDirectoryMappings">
<mapping directory="$PROJECT_DIR$/../.." vcs="Git" />
</component>
</project>

View file

@ -0,0 +1,44 @@
plugins {
id 'java'
id 'application'
id 'org.openjfx.javafxplugin' version '0.0.9'
id 'org.beryx.jlink' version '2.15.1'
}
group 'org.example'
version '1.0-SNAPSHOT'
sourceCompatibility = 11
repositories {
mavenCentral()
}
javafx {
version = "11.0.2"
modules = [ 'javafx.controls', 'javafx.fxml', 'javafx.graphics', 'javafx.base']
}
dependencies {
testImplementation 'org.junit.jupiter:junit-jupiter-api:5.6.0'
compile group: 'mysql', name: 'mysql-connector-java', version: '8.0.22'
testRuntimeOnly 'org.junit.jupiter:junit-jupiter-engine'
compile group: 'mysql', name: 'mysql-connector-java', version: '8.0.22'
runtimeOnly "org.openjfx:javafx-graphics:$javafx.version:win"
runtimeOnly "org.openjfx:javafx-graphics:$javafx.version:linux"
runtimeOnly "org.openjfx:javafx-graphics:$javafx.version:mac"
}
mainClassName = 'chatapp.Launcher'
jlink {
options = ['--strip-debug', '--compress', '2', '--no-header-files', '--no-man-pages']
launcher {
name = 'hellofx'
}
}
test {
useJUnitPlatform()
}

View file

@ -0,0 +1,53 @@
<?xml version="1.0" encoding="UTF-8"?>
<?import javafx.scene.control.Button?>
<?import javafx.scene.control.TextField?>
<?import javafx.scene.layout.AnchorPane?>
<?import javafx.scene.layout.ColumnConstraints?>
<?import javafx.scene.layout.GridPane?>
<?import javafx.scene.layout.HBox?>
<?import javafx.scene.layout.RowConstraints?>
<?import javafx.scene.layout.VBox?>
<?import javafx.scene.text.Font?>
<?import javafx.scene.text.Text?>
<AnchorPane maxHeight="-Infinity" maxWidth="-Infinity" minHeight="-Infinity" minWidth="-Infinity" prefHeight="400.0" prefWidth="600.0" xmlns="http://javafx.com/javafx/11.0.1" xmlns:fx="http://javafx.com/fxml/1" fx:controller="chatapp.View.ConnexionScreen">
<children>
<VBox prefHeight="400.0" prefWidth="600.0">
<children>
<HBox alignment="CENTER" prefHeight="100.0" prefWidth="200.0" style="-fx-background-color: #3299a8;">
<children>
<Text fill="#b0c926" strokeType="OUTSIDE" strokeWidth="0.0" text="ChatApp">
<font>
<Font name="OCR A Extended" size="48.0" />
</font>
</Text>
</children>
</HBox>
<HBox alignment="CENTER" prefHeight="304.0" prefWidth="600.0" style="-fx-background-color: #3299a8;">
<children>
<GridPane alignment="CENTER" prefHeight="302.0" prefWidth="279.0">
<columnConstraints>
<ColumnConstraints hgrow="SOMETIMES" minWidth="10.0" prefWidth="100.0" />
<ColumnConstraints hgrow="SOMETIMES" minWidth="10.0" prefWidth="100.0" />
</columnConstraints>
<rowConstraints>
<RowConstraints maxHeight="254.19998168945312" minHeight="10.0" prefHeight="123.19998779296876" vgrow="SOMETIMES" />
<RowConstraints maxHeight="217.80000152587894" minHeight="10.0" prefHeight="107.20001220703125" vgrow="SOMETIMES" />
</rowConstraints>
<children>
<TextField fx:id="pseudonyme" prefHeight="26.0" prefWidth="447.0" promptText="Pseudonyme" GridPane.columnSpan="2" />
<Button fx:id="connexionButton" alignment="CENTER" contentDisplay="CENTER" mnemonicParsing="false" onAction="#connexion" prefHeight="38.0" prefWidth="287.0" style="-fx-background-color: #b0c926;" text="Connexion" textFill="#3299a8" GridPane.columnSpan="2" GridPane.rowIndex="1">
<font>
<Font name="OCR A Extended" size="27.0" />
</font>
</Button>
</children>
</GridPane>
</children>
</HBox>
<HBox alignment="CENTER" layoutX="10.0" layoutY="10.0" prefHeight="0.0" prefWidth="600.0" style="-fx-background-color: #3299a8;" />
</children>
</VBox>
</children>
</AnchorPane>

View file

@ -0,0 +1,72 @@
<?xml version="1.0" encoding="UTF-8"?>
<?import javafx.scene.control.Button?>
<?import javafx.scene.control.TextField?>
<?import javafx.scene.layout.AnchorPane?>
<?import javafx.scene.layout.ColumnConstraints?>
<?import javafx.scene.layout.GridPane?>
<?import javafx.scene.layout.HBox?>
<?import javafx.scene.layout.RowConstraints?>
<?import javafx.scene.layout.VBox?>
<?import javafx.scene.text.Font?>
<?import javafx.scene.text.Text?>
<AnchorPane maxHeight="-Infinity" maxWidth="-Infinity" minHeight="-Infinity" minWidth="-Infinity" prefHeight="400.0" prefWidth="600.0" xmlns="http://javafx.com/javafx/11.0.1" xmlns:fx="http://javafx.com/fxml/1" fx:controller="chatapp.View.ChangementPseudo">
<children>
<VBox prefHeight="400.0" prefWidth="600.0">
<children>
<HBox alignment="CENTER" prefHeight="100.0" prefWidth="200.0" style="-fx-background-color: #3299a8;">
<children>
<Text fill="#b0c926" strokeType="OUTSIDE" strokeWidth="0.0" text="Changement Pseudo">
<font>
<Font name="OCR A Extended" size="48.0" />
</font>
</Text>
</children>
</HBox>
<HBox alignment="CENTER" prefHeight="304.0" prefWidth="600.0" style="-fx-background-color: #3299a8;">
<children>
<GridPane>
<columnConstraints>
<ColumnConstraints hgrow="SOMETIMES" minWidth="10.0" prefWidth="100.0" />
<ColumnConstraints hgrow="SOMETIMES" minWidth="10.0" prefWidth="100.0" />
</columnConstraints>
<rowConstraints>
<RowConstraints minHeight="10.0" prefHeight="30.0" vgrow="SOMETIMES" />
<RowConstraints minHeight="10.0" prefHeight="30.0" vgrow="SOMETIMES" />
<RowConstraints minHeight="10.0" prefHeight="30.0" vgrow="SOMETIMES" />
</rowConstraints>
<children>
<Button fx:id="validationButton" alignment="CENTER" contentDisplay="CENTER" mnemonicParsing="false" onAction="#validerPseudo" prefHeight="38.0" prefWidth="287.0" style="-fx-background-color: #b0c926;" text="Valider" textFill="#3299a8" GridPane.columnSpan="2" GridPane.rowIndex="2">
<font>
<Font name="OCR A Extended" size="27.0" />
</font>
</Button>
<TextField fx:id="pseudonyme" prefHeight="26.0" prefWidth="447.0" promptText="Pseudonyme" GridPane.columnSpan="2" GridPane.rowIndex="1" />
<Text fill="#b0c926" strokeType="OUTSIDE" strokeWidth="0.0" text="Ancien :">
<font>
<Font size="19.0" />
</font>
</Text>
<Text fx:id="pseudonyme1" fill="WHITE" strokeType="OUTSIDE" strokeWidth="0.0" text="Pseudo" GridPane.columnIndex="1">
<font>
<Font size="19.0" />
</font>
</Text>
</children>
</GridPane>
</children>
</HBox>
<HBox alignment="BOTTOM_RIGHT" prefHeight="63.0" prefWidth="600.0" style="-fx-background-color: #3299a8;">
<children>
<Button fx:id="MenuButton" alignment="CENTER" mnemonicParsing="false" onAction="#retourMenu" style="-fx-background-color: #b0c926;" text="Retour au menu" textFill="WHITE">
<font>
<Font name="OCR A Extended" size="18.0" />
</font>
</Button>
</children>
</HBox>
</children>
</VBox>
</children>
</AnchorPane>

View file

@ -0,0 +1,90 @@
<?xml version="1.0" encoding="UTF-8"?>
<?import javafx.scene.control.Button?>
<?import javafx.scene.control.TextArea?>
<?import javafx.scene.control.TextField?>
<?import javafx.scene.layout.AnchorPane?>
<?import javafx.scene.layout.ColumnConstraints?>
<?import javafx.scene.layout.GridPane?>
<?import javafx.scene.layout.HBox?>
<?import javafx.scene.layout.RowConstraints?>
<?import javafx.scene.layout.VBox?>
<?import javafx.scene.text.Font?>
<?import javafx.scene.text.Text?>
<AnchorPane maxHeight="-Infinity" maxWidth="-Infinity" minHeight="-Infinity" minWidth="-Infinity" prefHeight="400.0" prefWidth="600.0" xmlns="http://javafx.com/javafx/11.0.1" xmlns:fx="http://javafx.com/fxml/1" fx:controller="chatapp.View.Clavardage">
<children>
<VBox prefHeight="400.0" prefWidth="600.0">
<children>
<HBox alignment="CENTER" prefHeight="100.0" prefWidth="200.0" style="-fx-background-color: #3299a8;">
<children>
<Text fill="#b0c926" strokeType="OUTSIDE" strokeWidth="0.0" text="Session de Clavardage">
<font>
<Font name="OCR A Extended" size="48.0" />
</font>
</Text>
</children>
</HBox>
<HBox alignment="CENTER" prefHeight="304.0" prefWidth="600.0" style="-fx-background-color: #3299a8;">
<children>
<GridPane prefHeight="282.0" prefWidth="402.0">
<columnConstraints>
<ColumnConstraints hgrow="SOMETIMES" minWidth="10.0" prefWidth="100.0" />
</columnConstraints>
<rowConstraints>
<RowConstraints maxHeight="257.0" minHeight="10.0" prefHeight="44.0" vgrow="NEVER" />
<RowConstraints maxHeight="257.0" minHeight="10.0" prefHeight="228.0" vgrow="NEVER" />
<RowConstraints maxHeight="257.0" minHeight="10.0" prefHeight="42.0" vgrow="NEVER" />
</rowConstraints>
<children>
<GridPane GridPane.rowIndex="2">
<columnConstraints>
<ColumnConstraints hgrow="SOMETIMES" maxWidth="327.0" minWidth="10.0" prefWidth="327.0" />
<ColumnConstraints hgrow="SOMETIMES" maxWidth="156.0" minWidth="10.0" prefWidth="75.0" />
</columnConstraints>
<rowConstraints>
<RowConstraints />
<RowConstraints maxHeight="79.0" minHeight="0.0" prefHeight="60.0" vgrow="SOMETIMES" />
</rowConstraints>
<children>
<TextField fx:id="AEnvoyer" prefHeight="26.0" prefWidth="447.0" promptText="Enter Text" GridPane.rowIndex="1" />
<Button fx:id="EnvoyerButton" mnemonicParsing="false" onAction="#envoyerMessage" prefHeight="27.0" prefWidth="73.0" text="Envoyer" GridPane.columnIndex="1" GridPane.rowIndex="1" />
</children>
</GridPane>
<GridPane prefHeight="34.0" prefWidth="345.0">
<columnConstraints>
<ColumnConstraints hgrow="SOMETIMES" minWidth="10.0" prefWidth="100.0" />
<ColumnConstraints hgrow="SOMETIMES" minWidth="10.0" prefWidth="100.0" />
<ColumnConstraints halignment="RIGHT" hgrow="SOMETIMES" minWidth="10.0" prefWidth="100.0" />
</columnConstraints>
<rowConstraints>
<RowConstraints minHeight="10.0" prefHeight="30.0" vgrow="SOMETIMES" />
</rowConstraints>
<children>
<Text fill="#b0c926" strokeType="OUTSIDE" strokeWidth="0.0" text="Chat avec : ">
<font>
<Font size="19.0" />
</font>
</Text>
<Text fx:id="pseudonyme1" fill="WHITE" strokeType="OUTSIDE" strokeWidth="0.0" text="Pseudo" textAlignment="CENTER" wrappingWidth="133.16357421875" GridPane.columnIndex="1">
<font>
<Font size="19.0" />
</font>
</Text>
<Button fx:id="plusButton" mnemonicParsing="false" onAction="#ajouterMessagesHistorique" style="-fx-background-color: #b0c926;" text="+" textAlignment="RIGHT" textFill="WHITE" GridPane.columnIndex="2">
<font>
<Font name="OCR A Extended" size="16.0" />
</font>
</Button>
</children>
</GridPane>
<TextArea fx:id="ChatText" prefHeight="200.0" prefWidth="200.0" GridPane.rowIndex="1" />
</children>
</GridPane>
</children>
</HBox>
<HBox alignment="BOTTOM_RIGHT" prefHeight="63.0" prefWidth="600.0" style="-fx-background-color: #3299a8;" />
</children>
</VBox>
</children>
</AnchorPane>

View file

@ -0,0 +1,62 @@
<?xml version="1.0" encoding="UTF-8"?>
<?import javafx.scene.control.Button?>
<?import javafx.scene.control.ComboBox?>
<?import javafx.scene.layout.AnchorPane?>
<?import javafx.scene.layout.ColumnConstraints?>
<?import javafx.scene.layout.GridPane?>
<?import javafx.scene.layout.HBox?>
<?import javafx.scene.layout.RowConstraints?>
<?import javafx.scene.layout.VBox?>
<?import javafx.scene.text.Font?>
<?import javafx.scene.text.Text?>
<AnchorPane maxHeight="-Infinity" maxWidth="-Infinity" minHeight="-Infinity" minWidth="-Infinity" prefHeight="400.0" prefWidth="600.0" xmlns="http://javafx.com/javafx/11.0.1" xmlns:fx="http://javafx.com/fxml/1" fx:controller="chatapp.View.DemarrerSession">
<children>
<VBox prefHeight="400.0" prefWidth="600.0">
<children>
<HBox alignment="CENTER" prefHeight="100.0" prefWidth="200.0" style="-fx-background-color: #3299a8;">
<children>
<Text fill="#b0c926" strokeType="OUTSIDE" strokeWidth="0.0" text="Démarrer Session">
<font>
<Font name="OCR A Extended" size="48.0" />
</font>
</Text>
</children>
</HBox>
<HBox alignment="CENTER" prefHeight="304.0" prefWidth="600.0" style="-fx-background-color: #3299a8;">
<children>
<GridPane prefHeight="166.0" prefWidth="350.0">
<columnConstraints>
<ColumnConstraints hgrow="SOMETIMES" minWidth="10.0" prefWidth="100.0" />
<ColumnConstraints hgrow="SOMETIMES" minWidth="10.0" prefWidth="100.0" />
</columnConstraints>
<rowConstraints>
<RowConstraints maxHeight="135.60001220703126" minHeight="10.0" prefHeight="88.20001220703125" vgrow="SOMETIMES" />
<RowConstraints maxHeight="201.9999984741211" minHeight="10.0" prefHeight="100.79998016357423" vgrow="SOMETIMES" />
<RowConstraints maxHeight="201.9999984741211" minHeight="10.0" prefHeight="112.80001983642575" vgrow="SOMETIMES" />
</rowConstraints>
<children>
<Text fill="#b0c926" strokeType="OUTSIDE" strokeWidth="0.0" text="Choix d'un contact" GridPane.columnSpan="2">
<font>
<Font name="OCR A Extended" size="26.0" />
</font>
</Text>
<ComboBox fx:id="choixContact" onAction="#demarrerSessionAvec" prefHeight="26.0" prefWidth="355.0" GridPane.columnSpan="2" GridPane.rowIndex="1" />
</children>
</GridPane>
</children>
</HBox>
<HBox alignment="BOTTOM_RIGHT" prefHeight="63.0" prefWidth="600.0" style="-fx-background-color: #3299a8;">
<children>
<Button fx:id="MenuButton" alignment="CENTER" mnemonicParsing="false" onAction="#retourMenu" style="-fx-background-color: #b0c926;" text="Retour au menu" textFill="WHITE">
<font>
<Font name="OCR A Extended" size="18.0" />
</font>
</Button>
</children>
</HBox>
</children>
</VBox>
</children>
</AnchorPane>

View file

@ -0,0 +1,54 @@
<?xml version="1.0" encoding="UTF-8"?>
<?import javafx.scene.control.Menu?>
<?import javafx.scene.control.MenuBar?>
<?import javafx.scene.control.MenuItem?>
<?import javafx.scene.layout.AnchorPane?>
<?import javafx.scene.layout.ColumnConstraints?>
<?import javafx.scene.layout.GridPane?>
<?import javafx.scene.layout.RowConstraints?>
<?import javafx.scene.layout.VBox?>
<?import javafx.scene.text.Font?>
<?import javafx.scene.text.Text?>
<VBox prefHeight="400.0" prefWidth="640.0" style="-fx-background-color: #3299a8;" xmlns="http://javafx.com/javafx/11.0.1" xmlns:fx="http://javafx.com/fxml/1" fx:controller="chatapp.View.View_Menu">
<children>
<MenuBar prefWidth="640.0" VBox.vgrow="NEVER">
<menus>
<Menu mnemonicParsing="false" text="Options">
<items>
<MenuItem fx:id="utilsActifsButton" onAction="#afficherUtilsActifs" mnemonicParsing="false" text="Utilisateurs actifs" />
<MenuItem fx:id="demarrerSessionButton" onAction="#demarrerSession" mnemonicParsing="false" text="Démarrer session" />
<MenuItem fx:id="changerPseudoButton" onAction="#changerPseudo" mnemonicParsing="false" text="Changer de pseudo" />
<MenuItem onAction="#deconnexion" mnemonicParsing="false" text="Déconnexion" />
</items>
</Menu>
</menus>
</MenuBar>
<AnchorPane maxHeight="-1.0" maxWidth="-1.0" prefHeight="-1.0" prefWidth="-1.0" VBox.vgrow="ALWAYS">
<children>
<GridPane layoutX="154.0" layoutY="119.0" prefHeight="82.0" prefWidth="392.0">
<columnConstraints>
<ColumnConstraints hgrow="SOMETIMES" minWidth="10.0" prefWidth="100.0" />
<ColumnConstraints hgrow="SOMETIMES" minWidth="10.0" prefWidth="100.0" />
</columnConstraints>
<rowConstraints>
<RowConstraints minHeight="10.0" prefHeight="30.0" vgrow="SOMETIMES" />
</rowConstraints>
<children>
<Text fill="#b0c926" strokeType="OUTSIDE" strokeWidth="0.0" text="Bienvenue">
<font>
<Font name="OCR A Extended" size="30.0" />
</font>
</Text>
<Text fx:id="pseudonyme" fill="WHITE" strokeType="OUTSIDE" strokeWidth="0.0" text="Pseudo" GridPane.columnIndex="1">
<font>
<Font name="OCR A Extended" size="30.0" />
</font>
</Text>
</children>
</GridPane>
</children>
</AnchorPane>
</children>
</VBox>

View file

@ -0,0 +1,53 @@
<?xml version="1.0" encoding="UTF-8"?>
<?import javafx.scene.control.Button?>
<?import javafx.scene.control.ScrollPane?>
<?import javafx.scene.control.TextArea?>
<?import javafx.scene.layout.AnchorPane?>
<?import javafx.scene.layout.HBox?>
<?import javafx.scene.layout.VBox?>
<?import javafx.scene.text.Font?>
<?import javafx.scene.text.Text?>
<AnchorPane maxHeight="-Infinity" maxWidth="-Infinity" minHeight="-Infinity" minWidth="-Infinity" prefHeight="400.0" prefWidth="600.0" xmlns="http://javafx.com/javafx/11.0.1" xmlns:fx="http://javafx.com/fxml/1" fx:controller="chatapp.View.View_Utilisateurs">
<children>
<VBox prefHeight="400.0" prefWidth="600.0">
<children>
<HBox alignment="CENTER" prefHeight="100.0" prefWidth="200.0" style="-fx-background-color: #3299a8;">
<children>
<Text fill="#b0c926" strokeType="OUTSIDE" strokeWidth="0.0" text="Qui est là?">
<font>
<Font name="OCR A Extended" size="48.0" />
</font>
</Text>
</children>
</HBox>
<HBox alignment="CENTER" prefHeight="304.0" prefWidth="600.0" style="-fx-background-color: #3299a8;">
<children>
<ScrollPane prefHeight="282.0" prefWidth="202.0">
<content>
<AnchorPane minHeight="0.0" minWidth="0.0" prefHeight="267.0" prefWidth="200.0">
<children>
<TextArea fx:id="ListeUtilisateurs" layoutY="12.0" prefHeight="267.2" prefWidth="200.0" style="-fx-background-color: #3299a8;" text="Aucun utilisateur actif" AnchorPane.bottomAnchor="0.0" AnchorPane.leftAnchor="0.0" AnchorPane.rightAnchor="0.0" AnchorPane.topAnchor="0.0">
<font>
<Font name="OCR A Extended" size="13.0" />
</font>
</TextArea>
</children>
</AnchorPane>
</content>
</ScrollPane>
</children>
</HBox>
<HBox alignment="BOTTOM_RIGHT" layoutX="10.0" layoutY="10.0" prefHeight="63.0" prefWidth="600.0" style="-fx-background-color: #3299a8;">
<children>
<Button fx:id="MenuButton" alignment="CENTER" mnemonicParsing="false" style="-fx-background-color: #b0c926;" onAction="#retourMenu" text="Retour au menu" textFill="WHITE">
<font>
<Font name="OCR A Extended" size="18.0" />
</font>
</Button>
</children></HBox>
</children>
</VBox>
</children>
</AnchorPane>

View file

@ -0,0 +1,39 @@
chatapp/Protocol/RunnerEcouteTCP.java
chatapp.Protocol.RunnerEcouteTCP
chatapp/View/DemarrerSession.java
chatapp.View.DemarrerSession
chatapp/Controller/ChatApp.java
chatapp.Controller.ChatApp
chatapp/Model/DataBase.java
chatapp.Model.DataBase
chatapp/View/ChangementPseudo.java
chatapp.View.ChangementPseudo
chatapp/Protocol/RunnerEcouteUDP.java
chatapp.Protocol.RunnerEcouteUDP
chatapp/Launcher.java
chatapp.Launcher
chatapp/Model/ListUtilisateurs.java
chatapp.Model.ListUtilisateurs
chatapp/Protocol/UDPEchange.java
chatapp.Protocol.RunnerUDP
chatapp.Protocol.UDPEchange
chatapp/Model/MessageHorodate.java
chatapp.Model.MessageHorodate
chatapp/Main.java
chatapp.Main
chatapp/View/View_Menu.java
chatapp.View.View_Menu
chatapp/Protocol/SessionClavardage.java
chatapp.Protocol.SessionClavardage
chatapp/View/ConnexionScreen.java
chatapp.View.ConnexionScreen
chatapp/View/View_Utilisateurs.java
chatapp.View.View_Utilisateurs
chatapp/Model/Utilisateur.java
chatapp.Model.Utilisateur
chatapp/View/FenetreSession.java
chatapp.View.FenetreSession
chatapp.View.FenetreSession$1
chatapp/View/Clavardage.java
chatapp.View.Clavardage
chatapp.View.Clavardage$1

Binary file not shown.

View file

@ -0,0 +1,5 @@
distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists
distributionUrl=https\://services.gradle.org/distributions/gradle-6.7-bin.zip
zipStoreBase=GRADLE_USER_HOME
zipStorePath=wrapper/dists

185
Implementation/chatapp/gradlew vendored Normal file
View file

@ -0,0 +1,185 @@
#!/usr/bin/env sh
#
# Copyright 2015 the original author or authors.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# https://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
#
##############################################################################
##
## Gradle start up script for UN*X
##
##############################################################################
# Attempt to set APP_HOME
# Resolve links: $0 may be a link
PRG="$0"
# Need this for relative symlinks.
while [ -h "$PRG" ] ; do
ls=`ls -ld "$PRG"`
link=`expr "$ls" : '.*-> \(.*\)$'`
if expr "$link" : '/.*' > /dev/null; then
PRG="$link"
else
PRG=`dirname "$PRG"`"/$link"
fi
done
SAVED="`pwd`"
cd "`dirname \"$PRG\"`/" >/dev/null
APP_HOME="`pwd -P`"
cd "$SAVED" >/dev/null
APP_NAME="Gradle"
APP_BASE_NAME=`basename "$0"`
# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"'
# Use the maximum available, or set MAX_FD != -1 to use that value.
MAX_FD="maximum"
warn () {
echo "$*"
}
die () {
echo
echo "$*"
echo
exit 1
}
# OS specific support (must be 'true' or 'false').
cygwin=false
msys=false
darwin=false
nonstop=false
case "`uname`" in
CYGWIN* )
cygwin=true
;;
Darwin* )
darwin=true
;;
MINGW* )
msys=true
;;
NONSTOP* )
nonstop=true
;;
esac
CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar
# Determine the Java command to use to start the JVM.
if [ -n "$JAVA_HOME" ] ; then
if [ -x "$JAVA_HOME/jre/sh/java" ] ; then
# IBM's JDK on AIX uses strange locations for the executables
JAVACMD="$JAVA_HOME/jre/sh/java"
else
JAVACMD="$JAVA_HOME/bin/java"
fi
if [ ! -x "$JAVACMD" ] ; then
die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME
Please set the JAVA_HOME variable in your environment to match the
location of your Java installation."
fi
else
JAVACMD="java"
which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
Please set the JAVA_HOME variable in your environment to match the
location of your Java installation."
fi
# Increase the maximum file descriptors if we can.
if [ "$cygwin" = "false" -a "$darwin" = "false" -a "$nonstop" = "false" ] ; then
MAX_FD_LIMIT=`ulimit -H -n`
if [ $? -eq 0 ] ; then
if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then
MAX_FD="$MAX_FD_LIMIT"
fi
ulimit -n $MAX_FD
if [ $? -ne 0 ] ; then
warn "Could not set maximum file descriptor limit: $MAX_FD"
fi
else
warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT"
fi
fi
# For Darwin, add options to specify how the application appears in the dock
if $darwin; then
GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\""
fi
# For Cygwin or MSYS, switch paths to Windows format before running java
if [ "$cygwin" = "true" -o "$msys" = "true" ] ; then
APP_HOME=`cygpath --path --mixed "$APP_HOME"`
CLASSPATH=`cygpath --path --mixed "$CLASSPATH"`
JAVACMD=`cygpath --unix "$JAVACMD"`
# We build the pattern for arguments to be converted via cygpath
ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null`
SEP=""
for dir in $ROOTDIRSRAW ; do
ROOTDIRS="$ROOTDIRS$SEP$dir"
SEP="|"
done
OURCYGPATTERN="(^($ROOTDIRS))"
# Add a user-defined pattern to the cygpath arguments
if [ "$GRADLE_CYGPATTERN" != "" ] ; then
OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)"
fi
# Now convert the arguments - kludge to limit ourselves to /bin/sh
i=0
for arg in "$@" ; do
CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -`
CHECK2=`echo "$arg"|egrep -c "^-"` ### Determine if an option
if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then ### Added a condition
eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"`
else
eval `echo args$i`="\"$arg\""
fi
i=`expr $i + 1`
done
case $i in
0) set -- ;;
1) set -- "$args0" ;;
2) set -- "$args0" "$args1" ;;
3) set -- "$args0" "$args1" "$args2" ;;
4) set -- "$args0" "$args1" "$args2" "$args3" ;;
5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;;
6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;;
7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;;
8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;;
9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;;
esac
fi
# Escape application args
save () {
for i do printf %s\\n "$i" | sed "s/'/'\\\\''/g;1s/^/'/;\$s/\$/' \\\\/" ; done
echo " "
}
APP_ARGS=`save "$@"`
# Collect all arguments for the java command, following the shell quoting and substitution rules
eval set -- $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS "\"-Dorg.gradle.appname=$APP_BASE_NAME\"" -classpath "\"$CLASSPATH\"" org.gradle.wrapper.GradleWrapperMain "$APP_ARGS"
exec "$JAVACMD" "$@"

89
Implementation/chatapp/gradlew.bat vendored Normal file
View file

@ -0,0 +1,89 @@
@rem
@rem Copyright 2015 the original author or authors.
@rem
@rem Licensed under the Apache License, Version 2.0 (the "License");
@rem you may not use this file except in compliance with the License.
@rem You may obtain a copy of the License at
@rem
@rem https://www.apache.org/licenses/LICENSE-2.0
@rem
@rem Unless required by applicable law or agreed to in writing, software
@rem distributed under the License is distributed on an "AS IS" BASIS,
@rem WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
@rem See the License for the specific language governing permissions and
@rem limitations under the License.
@rem
@if "%DEBUG%" == "" @echo off
@rem ##########################################################################
@rem
@rem Gradle startup script for Windows
@rem
@rem ##########################################################################
@rem Set local scope for the variables with windows NT shell
if "%OS%"=="Windows_NT" setlocal
set DIRNAME=%~dp0
if "%DIRNAME%" == "" set DIRNAME=.
set APP_BASE_NAME=%~n0
set APP_HOME=%DIRNAME%
@rem Resolve any "." and ".." in APP_HOME to make it shorter.
for %%i in ("%APP_HOME%") do set APP_HOME=%%~fi
@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
set DEFAULT_JVM_OPTS="-Xmx64m" "-Xms64m"
@rem Find java.exe
if defined JAVA_HOME goto findJavaFromJavaHome
set JAVA_EXE=java.exe
%JAVA_EXE% -version >NUL 2>&1
if "%ERRORLEVEL%" == "0" goto execute
echo.
echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
echo.
echo Please set the JAVA_HOME variable in your environment to match the
echo location of your Java installation.
goto fail
:findJavaFromJavaHome
set JAVA_HOME=%JAVA_HOME:"=%
set JAVA_EXE=%JAVA_HOME%/bin/java.exe
if exist "%JAVA_EXE%" goto execute
echo.
echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME%
echo.
echo Please set the JAVA_HOME variable in your environment to match the
echo location of your Java installation.
goto fail
:execute
@rem Setup the command line
set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar
@rem Execute Gradle
"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %*
:end
@rem End local scope for the variables with windows NT shell
if "%ERRORLEVEL%"=="0" goto mainEnd
:fail
rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of
rem the _cmd.exe /c_ return code!
if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1
exit /b 1
:mainEnd
if "%OS%"=="Windows_NT" endlocal
:omega

View file

@ -0,0 +1,2 @@
rootProject.name = 'chatapp'

View file

@ -0,0 +1,309 @@
package chatapp.Controller;
import chatapp.Model.*;
import chatapp.Protocol.*;
import javafx.application.Application;
import javafx.application.Platform;
import java.beans.PropertyChangeEvent;
import java.beans.PropertyChangeListener;
import java.io.IOException;
import java.net.InetAddress;
import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
public class ChatApp implements PropertyChangeListener {
/* Liste des utilisateurs actifs */
private ListUtilisateurs actifUsers ;
/* ChatApp est associe a un utilisateur */
private Utilisateur me;
/* ChatApp est associe a une application qui le lance et que chatapp doit fermer a la fin */
private Application main;
private static ChatApp chatapp = null;
private RunnerEcouteTCP runnerEcouteTCP;
private RunnerEcouteUDP runnerEcouteUDP;
private boolean connecte;
private DataBase db;
public boolean isConnecte() {
return connecte;
}
/**
* <p>Constructeur de l'application de chat</p>
*
* @param pseudo Pseudo de l'utilisateur
* @param port Port de communication
*/
public ChatApp(String pseudo, Integer port, Application main){
this.actifUsers = new ListUtilisateurs() ;
// Recuperer adresse IP de l'utilisateur
InetAddress ip = null ;
ip = UDPEchange.getCurrentIp();
this.me = new Utilisateur(pseudo,port,ip);
this.actifUsers.addList(getMe());
this.main = main;
this.db= DataBase.getInstance();
this.connecte=false;
}
/**
* <p>Methode permettant de créer qu'une seule instance de chatapp</p>
* @param pseudo le pseudonyme que l'on souhaite donner à l'utilisateur
* @param port le port auquel on souhaite receptionner les requêtees UDP
* @param main le stage de l'interface graphique qui crée l'instance
* @return une instance de chatapp
*/
public static synchronized ChatApp getInstance(String pseudo, Integer port, Application main){
if (chatapp == null) {
chatapp = new ChatApp(pseudo, port, main);
}
return chatapp;
}
/**
*
* @return recupere l'instance de chatapp qui a ete creee au prealable
*/
public static ChatApp getInstance(){
return chatapp;
}
/*public void majHistorique2(MessageHorodate mh, String pseudo) {
Historique h = getMapHistorique().get(pseudo);
//h.addMessage(mh);
getMapHistorique().put(h.getUser2().getPseudo(),h);
}*/
/**
* <p>Modification du pseudo de l'utilisateur
* Envoie en broadcast ses informations utilisateurs et son nouveau pseudo</p>
*
* @param nouveau correspond au nouveau pseudo
* @return False si modiferPseudo a echoue, True sinon
*/
public Boolean modifierPseudo(String nouveau) throws IOException {
// Message que l'on envoie à tous les utilisateurs actifs
String broadcastMessage = "Demande Modification Pseudo\n" + this.getMe().toString() + "\n" + nouveau + "\n";
UDPEchange.EnvoiBroadcast(broadcastMessage);
try {
Thread.sleep(2000);
/* L'utilisateur doit attendre la reponse de tous les utilisateurs connectes
* pour savoir si son pseudo est accepte
*/
} catch (InterruptedException e) {
e.printStackTrace();
}
if (UDPEchange.getPseudoValide()) {
System.out.println("Modification pseudo reussie");
//Envoi un msg en broadcast a tout les utilisateurs pour les prevenir de son nouveau pseudo//
broadcastMessage = "Modification pseudo reussie\n" + this.getMe().toString() + "\n" + nouveau + "\n";
UDPEchange.EnvoiBroadcast(broadcastMessage);
//-------Change son propre nom d'utilisateur-------//
this.getActifUsers().modifierList(this.getMe().getPseudo(), nouveau);
this.getMe().setPseudo(nouveau);
db.majPseudo(this.me.getId(),nouveau);
System.out.println("Changement pseudo accepte, nouvelle liste des utilisateurs actifs:");
this.getActifUsers().afficherListeUtilisateurs();
return true;
}
else
{
System.out.println("Echec Modification pseudo");
return false;
}
}
/**
* <p>Methode appelee lors de la connexion d'un nouvel utilisateur.
* Il va prevenir les utilisateurs du reseau de son arrivee.</p>
* @return False si Connexion a echoue, True sinon
*/
public Boolean connexion() throws IOException {
// Message que l'on envoie à tous les utilisateurs actifs
String broadcastMessage = "Connexion\n" + this.getMe().toString() ;
UDPEchange.EnvoiBroadcast(broadcastMessage);
try {
Thread.sleep(2000); // L'utilisateur doit attendre la reponse de tous les utilisateurs connectes
} catch (InterruptedException e) {
e.printStackTrace();
}
if (UDPEchange.getConnecte()) {
System.out.println("Connexion reussie");
return true;
}
else
{
System.out.println("Connexion echoue");
UDPEchange.setConnecte(true);
return false ;
}
}
/**
* <p>Methode appelee lors de la connexion de l'utilisateur, va prevenir les autres
* utlisateurs du reseau de l'arrivee de l'utilisateur sur celui-ci</p>
* @param pseudo le pseudonyme avec lequel l'utilisateur souhaite se connecter
* @return False si Connexion a echoue, True sinon
* @throws IOException
*/
public Boolean connexion(String pseudo) throws IOException {
// Message que l'on envoie à tous les utilisateurs actifs
this.me.setPseudo(pseudo);
String broadcastMessage = "Connexion\n" + this.getMe().toString() ;
UDPEchange.EnvoiBroadcast(broadcastMessage);
try {
Thread.sleep(2000); // L'utilisateur doit attendre la reponse de tous les utilisateurs connectes
} catch (InterruptedException e) {
e.printStackTrace();
}
if (UDPEchange.getConnecte()) {
System.out.println("Connexion reussie");
this.connecte=true;
this.db.ajoutUtilisateurs(this.me.getId(),pseudo);
this.db.majUtilisateursActifs(true,this.me.getId());
return true;
}
else
{
System.out.println("Connexion echoue");
UDPEchange.setConnecte(true);
return false ;
}
}
/**
* <p>Lance un thread pour ecouter les requetes TCP
* Informe le pcs que chatapp ecoute les notifications qu'il envoie</p>
*/
public void activerEcouteTCP(){
this.runnerEcouteTCP = new RunnerEcouteTCP(this);
this.runnerEcouteTCP.addPropertyChangeListener(this);
}
/**
* <p>Demarre une session de clavardage avec l'utilisateur dont le pseudo est entre en parametre</p>
* @param pseudo le pseudo de l'utilisateur avec lequel on souhaite communiquer
*/
public void demarrerSession(String pseudo){
Utilisateur u2 = this.actifUsers.getPseudoList(pseudo);
SessionClavardage session = new SessionClavardage(u2,this);
runnerEcouteTCP.addSession(session);
}
/**
* <p>Lance le thread pour receptionner les requetes UDP</p>
*/
public void activerEcouteUDP(){
this.runnerEcouteUDP = new RunnerEcouteUDP(this);
this.runnerEcouteUDP.start();
}
/**
* <p>Methode appelee lors de la deconnexion de l'utilisateur.
* Il va prevenir les utilisateurs du reseau de son depart.</p>
*
*/
public void deconnexion() throws IOException {
// Message que l'on envoie à tous les utilisateurs actifs
String broadcastMessage = "Deconnexion\n" + this.getMe().toString() ;
UDPEchange.EnvoiBroadcast(broadcastMessage);
db.majUtilisateursActifs(false,this.me.getId());
this.connecte=false;
try {
main.stop();
} catch (Exception e) {
e.printStackTrace();
}
Platform.exit();
System.exit(0);
}
/**
* Getter
* @return Utilisateur associee a ChatApp
*/
public Utilisateur getMe() {
return me;
}
/**
* Getter
* @return Liste des utilisateurs actifs associee a ChatApp
*/
public ListUtilisateurs getActifUsers() {
return actifUsers;
}
/*public static void main (String[] args) throws IOException {
ChatApp app = new ChatApp(args[0],Integer.parseInt(args[1]),this.app) ;
System.out.println("On lance le chatapp");
ExecutorService execUDP = Executors.newFixedThreadPool(1000);
execUDP.submit(new RunnerEcouteUDP(app));
try {
app.connexion();
} catch (IOException e) {
e.printStackTrace();
}
ExecutorService execTCP = Executors.newFixedThreadPool(1000);
System.out.println("On lance l'écoute TCP de chatapp");
execTCP.submit(new RunnerEcouteTCP(app));
try {
Thread.sleep(5000);
} catch (InterruptedException e) {
e.printStackTrace();
}
if(app.getMe().getPseudo().equals("Marvel")) {
app.getHist("Doudou").afficher10derniers();
System.out.println("Tentative de connexion avec Doudou");
TCPEchange.demarrerSession(app, app.actifUsers.getPseudoList("Doudou"));
}
}*/
/**
* <p>Handler des differents evenements que chatapp ecoute</p>
* @param evt l'evenement qui a ete indique par le pcs
*/
@Override
public void propertyChange(PropertyChangeEvent evt) {
switch (evt.getPropertyName()){
case "chatCreated" :
SessionClavardage session = this.runnerEcouteTCP.getSessionClavardage();
session.addPropertyChangeListener(this);
break;
}
}
/**
* <p>Permet de recuperer stage de l'interface graphique qui a cree l'instance</p>
* @return le stage de l'interface graphique qui a cree l'instance
*/
public Application getMain() {
return main;
}
/**
* <p>Permet de recuperer la base de donnee associee</p>
* @return la base de donnee associee
*/
public DataBase getDb(){return this.db;}
}

View file

@ -0,0 +1,7 @@
package chatapp;
public class Launcher {
public static void main(String[] args) {
Main.main(args);
}
}

View file

@ -0,0 +1,62 @@
package chatapp;
import chatapp.Controller.ChatApp;
import javafx.application.Application;
import javafx.application.Platform;
import javafx.fxml.FXMLLoader;
import javafx.geometry.Rectangle2D;
import javafx.scene.Scene;
import javafx.stage.Screen;
import javafx.stage.Stage;
import java.io.IOException;
public class Main extends Application {
ChatApp chatapp;
/**
* Permet de lancer la fenetre principale de l'application
* @param primaryStage notre fenetre principale
* @throws Exception
*/
@Override
public void start(Stage primaryStage) throws Exception {
Rectangle2D tailleEcran = Screen.getPrimary().getBounds();
this.chatapp = ChatApp.getInstance("Null",1234,this);
FXMLLoader fichier = new FXMLLoader(getClass().getResource("/fenetres/ConnexionScreen.fxml"));
Scene scene1 = new Scene(fichier.load(),600,400);
primaryStage.setScene(scene1);
primaryStage.setTitle("ChatApp");
primaryStage.setMinWidth(600);
primaryStage.setMinHeight(400);
//primaryStage.setMaxWidth(600);
//primaryStage.setMaxHeight(400);
/*primaryStage.setMaxWidth(tailleEcran.getWidth());
primaryStage.setMaxHeight(tailleEcran.getHeight());*/
primaryStage.show();
primaryStage.centerOnScreen();
chatapp.activerEcouteTCP();
chatapp.activerEcouteUDP();
}
/**
* <p> Handler associe a la fermeture de l'application</p>
* @throws Exception
*/
@Override
public void stop() throws Exception {
if(chatapp.isConnecte()){
chatapp.deconnexion();
}
else {
super.stop();
Platform.exit();
System.exit(0);
}
}
public static void main(String[] args) {
launch(args);
}
}

View file

@ -0,0 +1,482 @@
package chatapp.Model;
import java.sql.*;
/**
* <p>
* Classe representant la Base de données.
* Celle-ci stocke la liste des utilisateurs ainsi que les échanges entre eux
* </p>
*/
public class DataBase {
private final String DBurl = "jdbc:mysql://srv-bdens.insa-toulouse.fr:3306" ;
private Connection connection = null;
private final String login = "tp_servlet_006";
private final String pswd = "baePh9ei";
/*Format de la table Utilisateurs
+--------+-------------+---------+---------------------+
| ID | Pseudo | Actif | Date d'inscription |
+--------+-------------+---------+---------------------+
Id correspond à l'addresse IP
Pseudo : Dernier Pseudo utilisé pour cette adresse IP, va etre remplacé par le pseudo actuel avec majPseudo
Date d'inscription comme son nom l'indique le jour de l'inscription de cette utilisateur
Actif est un boolean indicant si l'utilisateur est actif
Chaque communication entres utilisateurs sera stocké dans une table de la forme
+------------------+-----------+---------------+---------------+
| Destinataire | Source | Message | Date d'envoi |
+--------+---------------------+---------------+---------------+
Destinataire -> Id du destinataire du message
Source -> Id de celui qui envoie le message
Message -> Msg envoye
Date d'envoie -> Date a laquelle Source a envoye le message a destinataire
*/
private static final DataBase instance = null; // Singleton
/**
* Constructeur de la database
* On installe le driver et on établit la connection.
*/
public DataBase() {
try {
//Besoin d'installer le driver JDBC entre java IDE et le system DBMS pour faire un pont entre les deux
Class.forName("com.mysql.cj.jdbc.Driver");
System.out.println("Driver Installe");
} catch (ClassNotFoundException e) {
e.printStackTrace();
System.out.println("Echec installation Driver");
}
try {
//Etablir une connexion , forme : (url, "myLogin", "myPassword");
// Nabil : DECOMMENTER CETTE LIGNE
//this.connection = DriverManager.getConnection("jdbc:mysql://localhost/POO_AL_NM?allowPublicKeyRetrieval=true&useSSL=false", "root", "1234");
// Auriane : DECOMMENTER CETTE LIGNE
this.connection = DriverManager.getConnection("jdbc:mysql://localhost:8889/POO_AL_NM?allowPublicKeyRetrieval=true&useSSL=false", "root", "root");
//this.connection = DriverManager.getConnection(this.DBurl,login,pswd);
System.out.println("Connexion Etablie");
} catch (SQLException e) {
e.printStackTrace();
System.out.println("Echec d'etablissement de la connexion");
}
}
/**
* Méthode permettant de renvoyer une instance de la classe DataBase
* @return Retourne l'instance du singleton DataBase.
*/
public static DataBase getInstance() {
synchronized (DataBase.class) {
return new DataBase();
}
}
/**
* Methode permettant de creer une table pour stocker les messages entre deux utilisateurs
* @param ID1 Id du premier utilisateur
* @param ID2 Id du second utilisateur
*/
public void CreationTableHistorique(String ID1 , String ID2) {
// Pour eviter d'avoir les tables en double
String petit;
String grand;
int comparaison = ID1.compareTo(ID2);
if (comparaison < 0) {
petit = ID1;
grand = ID2 ;
}
else {
petit = ID2;
grand = ID1 ;
}
String nomTable = "Chat_" + petit + "_" + grand ;
String Requete = "CREATE TABLE IF NOT EXISTS`" + nomTable +"` (\n" + "`Destinataire` varchar(100) NOT NULL,\n" + " `Source` varchar(100) NOT NULL,\n" + " `Envoi` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,\n" + " `Message` text NOT NULL\n" + ") ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 ;";
System.out.println(Requete);
PreparedStatement Ps = null ;
//Statement est utilisé pour envoyer une requete SQL à la base de donnee
try {
Ps = connection.prepareStatement(Requete);
System.out.println("Statement cree");
} catch (SQLException e) {
e.printStackTrace();
System.out.println("Echec creation Statement");
}
//Execute la donnée SQL statement passe en parametre
try {
assert Ps != null;
Ps.executeUpdate();
} catch (SQLException e) {
e.printStackTrace();
System.out.println(" Echec executeUpdate ");
}
}
/**
* Methode permettant de mettre a jour le pseudo d'un utilisateur en fonction de son ID dans la base de donnee
* @param ID Id de l'utilisateur qui vient de changer de pseudo
* @param Pseudo Nouveau Pseudo de l'utilisateur
*/
public void majPseudo( String ID , String Pseudo) {
String requete= "UPDATE `Utilisateurs` SET `Pseudo`=? WHERE id=?";
PreparedStatement Ps = null ;
//Statement est utilisé pour envoyer une requete SQL à la base de donnee
try {
Ps = connection.prepareStatement(requete);
Ps.setString(1, Pseudo); // ? n°1 devient la valeur contenu dans Pseudo
Ps.setString(2, ID); // ? n°2 devient la valeur contenu dans ID
System.out.println("Statement cree");
} catch (SQLException e) {
e.printStackTrace();
System.out.println("Echec creation Statement");
}
//Execute la donnée SQL statement passe en parametre
try {
assert Ps != null;
Ps.executeUpdate();
} catch (SQLException e) {
e.printStackTrace();
System.out.println(" Echec executeUpdate ");
}
}
/**
* Methode permettant de mettre a jour le pseudo d'un utilisateur en fonction de son ID dans la base de donnee
* @param IDdest Id de l'utilisateur Destinataire du message
* @param IDsrc Id de celui qui envoi le message
* @param Msg Message envoye entre les deux utilisateurs
*/
public void ajoutHistorique(String IDdest , String IDsrc, String Msg) {
String petit;
String grand;
int comparaison = IDdest.compareTo(IDsrc);
if (comparaison < 0) {
petit = IDdest;
grand = IDsrc ;
}
else {
petit = IDsrc;
grand = IDdest ;
}
String nomTable = "Chat_" + petit + "_" + grand ;
String requete= "INSERT INTO `"+ nomTable +"`(`Destinataire`, `Source`, `Message`) VALUES ( ? , ? , ?)";
PreparedStatement Ps = null ;
//Statement est utilisé pour envoyer une requete SQL à la base de donnee
try {
Ps = connection.prepareStatement(requete);
Ps.setString(1, IDdest); // ? n°1 devient la valeur contenu dans IDdest
Ps.setString(2, IDsrc); // ? n°2 devient la valeur contenu dans IDsrc
Ps.setString(3, Msg); // ? n°3 devient la valeur contenu dans Msg
//La date de l'envoi n'a pas besoin d'être renseigné, elle est automatique
System.out.println("Statement cree");
} catch (SQLException e) {
e.printStackTrace();
System.out.println("Echec creation Statement");
}
//Execute la donnée SQL statement passe en parametre
try {
assert Ps != null;
Ps.executeUpdate();
} catch (SQLException e) {
e.printStackTrace();
System.out.println(" Echec executeUpdate ");
}
}
/**
* Methode permettant d'ajouter un utilisateur dans la base de donnée si celui-ci n'existe pas deja
* @param ID Id de l'utilisateur que l'on veut rajouter
* @param Pseudo pseudo actuelle de l'utilisateur
*/
public void ajoutUtilisateurs(String ID , String Pseudo ) {
if(this.idExiste(ID)){
this.majPseudo(ID, Pseudo);
}
else {
// L'utilisateur n'existe pas , on va le rajouter.
System.out.println("On rajoute l'utilisateur " + Pseudo);
String requete = "INSERT INTO `Utilisateurs` (`ID`, `Pseudo`, `Actif`) VALUES ( ? , ? , '1')";
PreparedStatement Ps = null;
//Statement est utilisé pour envoyer une requete SQL à la base de donnee
try {
Ps = connection.prepareStatement(requete);
Ps.setString(1, ID); // ? n°1 devient la valeur contenu dans ID
Ps.setString(2, Pseudo); // ? n°2 devient la valeur contenu dans Pseudo
System.out.println("Statement cree");
} catch (SQLException e) {
e.printStackTrace();
System.out.println("Echec creation Statement");
}
//Execute la donnée SQL statement passe en parametre
try {
assert Ps != null;
Ps.executeUpdate();
} catch (SQLException e) {
e.printStackTrace();
System.out.println(" Echec executeUpdate ");
}
}
}
/**
* Methode permettant de mettre a jour les utilisateurs actuellement actif
* @param Id Id de l'utilisateur qui vient de se connecter ou deconnecter
* @param Connecte Boolean true si il est connecte , false sinon
*/
public void majUtilisateursActifs(Boolean Connecte, String Id) {
String requete= "UPDATE `Utilisateurs` SET `Actif`=? WHERE id=?";
PreparedStatement Ps = null ;
int Actif = Connecte ? 1 : 0; // True -> 1 , False -> 0
//Statement est utilisé pour envoyer une requete SQL à la base de donnee
try {
Ps = connection.prepareStatement(requete);
Ps.setInt(1, Actif); // ? n°1 devient la valeur contenu dans Actif (1 ou 0)
Ps.setString(2, Id); // // ? n°2 devient la valeur contenu dans Id
System.out.println("Statement cree");
} catch (SQLException e) {
e.printStackTrace();
System.out.println("Echec creation Statement");
}
//Execute la donnée SQL statement passe en parametre
try {
assert Ps != null;
Ps.executeUpdate();
} catch (SQLException e) {
e.printStackTrace();
System.out.println(" Echec executeUpdate ");
}
}
/**
* Methode permettant de recuperer les N derniers messages envoyés entre 2 utilisateurs
* @param ID Utilisateur associé a ChatApp
* @param IDdestinataire Celui avec qui correspond ID
* @param N le nombre de messages souhaités
* @return Les N derniers Messages
*/
public String recupNMsg(String ID, String IDdestinataire, int N) {
StringBuilder Msg = new StringBuilder();
String petit;
String grand;
int comparaison = ID.compareTo(IDdestinataire);
if (comparaison < 0) {
petit = ID;
grand = IDdestinataire;
}
else {
petit = IDdestinataire;
grand = ID ;
}
String nomTable = "Chat_" + petit + "_" + grand ;
String requete = "SELECT * FROM `"+ nomTable +"`";
Statement stmt = null;
ResultSet rs = null ;
try {
stmt = this.connection.createStatement();
} catch (SQLException throwables) {
throwables.printStackTrace();
}
try {
assert stmt != null;
rs = stmt.executeQuery(requete);
} catch (SQLException throwables) {
throwables.printStackTrace();
}
Integer Taille = tailleBDD(nomTable);
if(Taille < N ){
N = Taille ;
}
for(int i = 0 ; i < N; i++){
try {
assert rs != null;
if( rs.next()){
String IDSource = rs.getString("Source");
String Envoi = rs.getTimestamp("Envoi").toString();
String Message = rs.getString("Message");
if (IDSource.equals(ID)) Msg.append("Moi (").append(Envoi).append(") : ").append(Message);
else {
String PseudoSource = getPseudo(IDSource) ;
Msg.append(PseudoSource).append(" (").append(Envoi).append(") : ").append(Message);
}
Msg.append('\n');
}
// MSG de la forme :
// Source (Date) : Texte
} catch (SQLException throwables) {
throwables.printStackTrace();
}
}
return Msg.toString();
}
/**
* Methode permettant de recuperer le pseudo actuel d'un utilisateur en fonction de son ID
* @param idSource Id de l'utilsateur dont on veut connaitre le pseudo
* @return Pseudo
*/
private String getPseudo(String idSource) {
String Pseudo = "" ;
String requete= "SELECT * FROM `Utilisateurs` WHERE `ID` LIKE '" + idSource + "'";
Statement stmt = null;
ResultSet rs = null ;
try {
stmt = this.connection.createStatement();
} catch (SQLException throwables) {
throwables.printStackTrace();
}
try {
assert stmt != null;
rs = stmt.executeQuery(requete);
} catch (SQLException throwables) {
throwables.printStackTrace();
}
try {
assert rs != null;
if (rs.next()){
Pseudo = rs.getString("Pseudo") ;
}
} catch (SQLException throwables) {
throwables.printStackTrace();
}
return Pseudo ;
}
/**
* Methode permettant de recuperer les messages d'une plage de donnée [deb,fin] envoyés entre 2 utilisateurs
* @param ID Utilisateur associé a ChatApp
* @param IDdestinataire Celui avec qui correspond ID
* @param deb On veut les messages à partir de l'indice deb
* @param fin On veut les messages jusqu'a l'indice fin
* @return Les messages d'une plage de donnée [deb,fin]
*/
public String recupMsg(String ID, String IDdestinataire, int deb , int fin) {
StringBuilder Msg = new StringBuilder();
String petit;
String grand;
int comparaison = ID.compareTo(IDdestinataire);
if (comparaison < 0) {
petit = ID;
grand = IDdestinataire;
}
else {
petit = IDdestinataire;
grand = ID ;
}
String nomTable = "Chat_" + petit + "_" + grand ;
String requete = "SELECT * FROM `"+ nomTable+"`";
Statement stmt = null;
ResultSet rs = null ;
try {
stmt = this.connection.createStatement();
} catch (SQLException throwables) {
throwables.printStackTrace();
}
try {
assert stmt != null;
rs = stmt.executeQuery(requete);
} catch (SQLException throwables) {
throwables.printStackTrace();
}
Integer Taille = tailleBDD(nomTable);
if(Taille < fin ){
fin = Taille ;
}
for(int i = 0 ; i < fin; i++){
try {
assert rs != null;
if( rs.next()){
String IDSource = rs.getString("Source");
String Envoi = rs.getTimestamp("Envoi").toString();
String Message = rs.getString("Message");
if (i >= deb) {
if (IDSource.equals(ID)) {
Msg.append("Moi (").append(Envoi).append(") : ").append(Message);
} else {
String PseudoSource = getPseudo(IDSource);
Msg.append(PseudoSource).append(" (").append(Envoi).append(") : ").append(Message);
}
Msg.append('\n');
}
}
} catch (SQLException throwables) {
throwables.printStackTrace();
}
}
return Msg.toString();
}
/**
* Cette méthode sert à recuperer la taille d'un base de donnée
* @param nomTable Nom de la table de donnée dont on veut récuperer le nom
* @return Taille de la BDD
*/
public Integer tailleBDD(String nomTable) {
Integer Taille = 0 ;
String requete = "SELECT * FROM `"+nomTable+ "`";
Statement stmt = null;
ResultSet rs = null ;
try {
stmt = this.connection.createStatement();
} catch (SQLException throwables) {
throwables.printStackTrace();
}
try {
assert stmt != null;
rs = stmt.executeQuery(requete);
} catch (SQLException throwables) {
throwables.printStackTrace();
}
while(true){
try {
assert rs != null;
if (!rs.next()) break;
} catch (SQLException throwables) {
throwables.printStackTrace();
}
Taille++; // on incremente Taille pour chaque solution trouvée
}
return Taille;
}
/**
* Methode permettant de savoir si un utilisateur existe dans la base de donnée 'Utilisateurs'
* @param ID On recherche l'utilisateur dont l'ID est ID
* @return True si l'utilisateur existe , False sinon
*/
public boolean idExiste(String ID){
boolean existe = false ;
// Verification que l'utilisateur n'existe pas
String requete = "SELECT * FROM `Utilisateurs` WHERE `ID` LIKE '" + ID +"'";
Statement stmt;
ResultSet rs = null ;
try {
stmt = this.connection.createStatement();
rs = stmt.executeQuery(requete);
} catch (SQLException throwables) {
throwables.printStackTrace();
}
existe = (!rs.equals(null));
return existe;
}
public String getNomTable(Utilisateur U1, Utilisateur U2){
String petit;
String grand;
int comparaison;
comparaison = U1.getId().compareTo(U2.getId());
if (comparaison < 0) {
petit = U1.getId();
grand = U2.getId();
}
else {
petit = U2.getId() ;
grand = U1.getId() ;
}
return "Chat_" + petit + "_" + grand ;
}
}

View file

@ -0,0 +1,142 @@
package chatapp.Model;
import java.net.InetAddress;
import java.util.ArrayList;
/**
* <p>
* Classe representant La liste des utilisateurs actifs, stockée localement
* </p>
*/
public class ListUtilisateurs {
// On conserve dans cette liste tout les utilisateurs actuellement actifs
private ArrayList<Utilisateur> actifUsers ;
/**
* Constructeur : initialise la liste 'actifUsers'
*/
public ListUtilisateurs() {
this.actifUsers = new ArrayList<>() ;
}
/**
* Ajouter des utilisateurs actifs dans l'attribut liste 'actifUsers'
* @param u on va rajouter cet utilisateur dans la liste
*/
public void addList(Utilisateur u) {
if((verifierUnicite(u.getPseudo()))) {
this.actifUsers.add(u);
}
}
/**
* Recuperer un utilisateur a partir de son pseudo
* @param pseudo Pseudo de l'utilisateur que l'on souhaite retrouver
*/
public Utilisateur getPseudoList(String pseudo) {
for(Utilisateur elem: this.actifUsers)
{
if (elem.getPseudo().equals(pseudo) ) {
return elem ;
}
}
return null ;
}
/**
* Recuperer un utilisateur a partir de son addresse IP
* @param ip @IP de l'utilisateur que l'on souhaite retrouver
*/
public Utilisateur getIPList(InetAddress ip) throws Exception {
for(Utilisateur elem: this.actifUsers)
{
if (elem.getIp().equals(ip) ) {
return elem ;
}
}
throw new Exception("No such user with this IP address") ;
}
/**
* Supprimer de la liste des utilisateurs actifs 'actifUsers' un certain utilisateur
* @param u on va supprimer cet utilisateur dans la liste
*/
public void supprimerList(Utilisateur u) {
boolean Sup = false ;
for(Utilisateur elem: this.actifUsers)
{
if (elem.equals(u) ) {
this.actifUsers.remove(elem);
Sup = true ;
this.afficherListeUtilisateurs();
}
}
if (!Sup) {
System.out.println("Tentative de retirer un objet non contenu dans la liste");
}
}
/**
* Modifier le pseudo d'un utilisateur dans la liste des utilisateurs actifs 'actifUsers'
* @param ancien correspond au pseudo remplacer
* @param nouveau correspond au nouveau pseudo
*/
public void modifierList(String ancien , String nouveau) {
for(Utilisateur elem: this.actifUsers)
{
if (ancien.equals( elem.getPseudo() ) ) {
this.actifUsers.remove(elem);
elem.setPseudo(nouveau);
this.addList(elem);
}
}
this.afficherListeUtilisateurs();
}
/**
* Methode permettant de savoir si un utilisateur est contenu dans la liste 'actifUsers'
* @param u on souhait savoir si cette utilisateur appartient a la liste
* @return True si il appartient, false sinon
*/
public Boolean appartient(Utilisateur u) {
return this.actifUsers.contains(u);
}
/**
* Verifie qu'aucun autre utilisateur ne possede le meme pseudo
* @param pseudo on va supprimer cet utilisateur dans la liste
* @return True si aucun utilisateur de la liste possede ce pseudo, false sinon
*/
public Boolean verifierUnicite(String pseudo) {
for(Utilisateur elem: this.actifUsers)
{
if (pseudo.equals( elem.getPseudo() ) ) {
return false ;
}
}
return true;
}
/**
* Methode affichant la liste des utilisateurs actifs
*/
public void afficherListeUtilisateurs() {
System.out.println ("Liste des utilisateurs actifs : ");
StringBuilder Utilisateur = new StringBuilder();
for(Utilisateur elem: this.actifUsers)
{
System.out.println (elem.toString());
Utilisateur.append(elem).append("\n");
}
}
/**
* Getter
* @return La liste des utilisateurs actifs
*/
public ArrayList<Utilisateur> getActifUsers(){
return this.actifUsers;
}
}

View file

@ -0,0 +1,174 @@
package chatapp.Model;
import java.io.Serializable;
import java.text.DateFormat;
import java.text.SimpleDateFormat;
import java.util.Date;
/**
* <p>
* Classe representant les messages envoyes en TCP lors d'une session de clavardage.
* Un message Horodate est compose d'un destintaire, d'une source , d'un message et d'une date d'envoie.
* </p>
*/
public class MessageHorodate implements Serializable {
private Utilisateur destinataire ;
private Utilisateur source ;
private Date dateHorodatage ;
private int type; // 0 = debut de la communication, 1= message de communication, 2 = fin de la communicataion
private String Message;
/**
* <p>
* Constructeur , le message va etre horodate
* @param destinataire - Destinataire du message
* @param source - Source du message
* @param Message - Message envoye
* </p>
*/
public MessageHorodate(Utilisateur destinataire, Utilisateur source, String Message, int type) {
this.setDestinataire(destinataire) ;
this.setSource(source) ;
this.setMessage(Message) ;
this.setDateHorodatage(new Date());
this.type = type;
}
/**
* Setter: Date d'horodatage
* On modifie le date d'horodatage
*/
public void setDate(Date d) {
this.setDateHorodatage(d);
}
/**
* <p>
* Permet de creer une representation string du message
* @return Les differents attributs de la classe sous forme de string
* </p>
*/
@Override
public String toString() {
String Msg = "";
Msg += ("Destinataire::" + this.getDestinataire() + "\n") ;
Msg += ("Source::" + this.getSource()+ "\n") ;
Msg += ("Type::"+ this.type+ "\n");
Msg += ("Date::" + this.dateToString() + "\n") ;
Msg += ("Message::" + this.getMessage() + "\n" );
return Msg ;
}
/**
* <p>
* Permet de creer une representation string de la date d'horodatage
* @return La date d'horodatage du message en format yyyy/MM/dd HH:mm:ss
* </p>
*/
public String dateToString() {
DateFormat format = new SimpleDateFormat("yyyy/MM/dd HH:mm:ss");
return format.format(this.getDateHorodatage());
}
/**
* <p>
* Permet de re creer un message horodate a partir d'un string
* @return un messageHorodate
* </p>
*/
public static MessageHorodate stringToMessageHorodate(String s) {
String[] mots = s.split("\n");
Utilisateur destinataire = Utilisateur.stringToUtilisateur(mots[0].split("::")[1]);
Utilisateur source = Utilisateur.stringToUtilisateur(mots[1].split("::")[1]);
int type = Integer.parseInt(mots[2].split("::")[1]);
String payload = "";
for(int i=4; i< mots.length; i++) {
if(mots[i].startsWith("Message::")) {
mots[i]=mots[i].split("::")[1];
}
payload += mots[i]+"\n";
}
return new MessageHorodate(destinataire, source, payload, type);
}
/**
* Getter: Utilisateur Source
* @return Utilisateur a l'origine du message
*/
public Utilisateur getSource() {
return source;
}
/**
* Setter: Utilisateur Source
* On modifie l'utilisateur source
*/
public void setSource(Utilisateur source) {
this.source = source;
}
/**
* Getter: Utilisateur Destinataire
* @return Utilisateur recevant le message
*/
public Utilisateur getDestinataire() {
return destinataire;
}
/**
* Setter: Utilisateur Destinataire
* On modifie l'utilisateur Destinataire
*/
public void setDestinataire(Utilisateur destinataire) {
this.destinataire = destinataire;
}
/**
* Getter: Message envoye
* @return Le message envoye
*/
public String getMessage() {
return Message;
}
/**
* Setter: Message envoye
* On modifie le message envoye
*/
public void setMessage(String message) {
Message = message;
}
/**
* Getter: 'Type' du message
* @return On recupere le Type du message
*/
public int getType() {
return type;
}
/**
* Setter: 'Type' du message horodate
* On modifie l'integer 'Type'
*/
public void setType(int Type) {
this.type = type;
}
/**
* Getter: Date d'horodatage
* @return On recupere le date
*/
public Date getDateHorodatage() {
return dateHorodatage;
}
/**
* Setter: Date d'horodatage
* On modifie le date.
*/
public void setDateHorodatage(Date dateHorodatage) {
this.dateHorodatage = dateHorodatage;
}
}

View file

@ -0,0 +1,90 @@
package chatapp.Model;
import java.net.InetAddress;
import java.net.UnknownHostException;
/**
* <p>
* Classe representant un Utilisateur
* Un Utilisateur est associe avec un pseudo, un numero de port, une addresse IP ainsi qu'un ID.
* </p>
*/
public class Utilisateur {
private String pseudo ;
private Integer port;
private final InetAddress ip ;
private final String id ;
/**
* Constructeur : Utilisateur
* @param pseudo Le pseudo associe
* @param port
* @param ip
*/
public Utilisateur(String pseudo,Integer port, InetAddress ip ){
this.setPseudo(pseudo) ;
this.setPort(port);
this.ip = ip ;
this.id = ip.getHostName() ;
}
public String getPseudo() {
return pseudo;
}
public void setPseudo(String pseudo) {
this.pseudo = pseudo;
}
public Integer getPort() {
return port;
}
public void setPort(Integer port) {
this.port = port;
}
public InetAddress getIp() {
return ip;
}
public String getId() {
return id;
}
@Override
public String toString(){
String s = "";
s+="pseudo " + this.pseudo + " | ";
s+="port " + (this.port).toString() + " | ";
s+="ip " + (this.ip).toString() + " | ";
s+="id " + (this.id).toString() + " | ";
return s;
}
public static Utilisateur stringToUtilisateur(String s) {
String name;
Integer port = 0;
String ip = "" ;
String id = "";
String mots[] = s.split(" ");
name=mots[1];
port=Integer.parseInt(mots[4]);
ip=mots[7];
id=mots[10];
Utilisateur user = null;
try {
user = new Utilisateur(name,port,InetAddress.getByName(ip.split("/")[1]));
} catch (UnknownHostException e) {
e.printStackTrace();
}
return user;
}
public Boolean equals(Utilisateur u) {
return this.getId().equals( u.getId() ) ;
}
}

View file

@ -0,0 +1,92 @@
package chatapp.Protocol;
import chatapp.Controller.ChatApp;
import java.beans.PropertyChangeListener;
import java.beans.PropertyChangeSupport;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.ArrayList;
/**
* <p>
* Classe permettant de gérer les multiples connexions en TCP.
* Extend la classe Thread.
* </p>
*/
public class RunnerEcouteTCP extends Thread {
public ChatApp app ;
private PropertyChangeSupport pcs;
// on conserve les sessions actives dans un attribut liste
private ArrayList<SessionClavardage> ListeSessions = new ArrayList<>();
/**
* Constructeur
* @param app Un RunnerEcouteTCP est toujours associé a une application de Chat
*/
public RunnerEcouteTCP(ChatApp app) {
this.app = app ;
this.pcs = new PropertyChangeSupport(this);
this.start();
}
/**
* Permet aux classes qui appelle cette methode de connecter un PropertyChangeListener au PropertyChangeSupport
* @param pcl le propertyChangeListener qui va ecouter les evenements du propertyChangeSupport associe
*/
public void addPropertyChangeListener(PropertyChangeListener pcl) {
this.pcs.addPropertyChangeListener("NouvelleSession",pcl);
}
/**
* <p>
* Methode pour qu'un objet de la classe ChatApp soit constamment en a l'ecoute de potentielles connexions
* @param app L'utilisateur en ecoute de potentielles communications
* </p>
*/
public void ecouteTCP(ChatApp app) {
ServerSocket ss;
System.out.println("Ecoute TCP activee");
try {
ss = new ServerSocket(5000); // On ecoute sur le port 5000
System.out.println("Socket d'ecoute cree");
while(true) { // Ecoute en boucle
System.out.println("Attente Session de clavardage");
Socket link = ss.accept(); // Blocante
SessionClavardage session = new SessionClavardage(link,app);
this.ListeSessions.add(session);
pcs.firePropertyChange("NouvelleSession",false,true);
}
}
catch (Exception e) {
e.printStackTrace();
}
}
/**
* Methode permettant d'ajouter une session active dans la liste 'ListeSessions'
* @param session Session Active que l'on souhaite rajouter
*/
public void addSession(SessionClavardage session){
this.ListeSessions.add(session);
pcs.firePropertyChange("NouvelleSession",false,true);
}
/**
* Methode permettant de recupere la derniere session de clavardage creee dans 'ListeSessions'
* @return Premiere Session Active
*/
public SessionClavardage getSessionClavardage() {
return(this.ListeSessions.remove(0));
}
/**
* Methode qui vient ecraser la méthode run de la classe Thread.
* La méthode 'ecouteTCP' est appele.
*/
@Override
public void run() {
ecouteTCP(this.app);
}
}

View file

@ -0,0 +1,16 @@
package chatapp.Protocol;
import chatapp.Controller.ChatApp;
public class RunnerEcouteUDP extends Thread {
ChatApp app ;
public RunnerEcouteUDP(ChatApp app) {
this.app = app ;
}
@Override
public void run() {
UDPEchange.ecouteUDP(app);
}
}

View file

@ -0,0 +1,186 @@
package chatapp.Protocol;
import java.beans.PropertyChangeListener;
import java.beans.PropertyChangeSupport;
import java.io.IOException;
import java.io.InputStream;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.io.OutputStream;
import java.net.Socket;
import java.util.ArrayList;
import chatapp.Controller.ChatApp;
import chatapp.Model.DataBase;
import chatapp.Model.MessageHorodate;
import chatapp.Model.Utilisateur;
import chatapp.View.FenetreSession;
import javafx.application.Platform;
public class SessionClavardage extends Thread {
private Socket link;
private ChatApp app;
private Utilisateur u2;
private ObjectOutputStream out;
private ObjectInputStream in;
private PropertyChangeSupport pcs;
private ArrayList<MessageHorodate> derniersMsg; // on met temporairement les derniers msgs pour éviter les pb de synchro inter-threads
private int SessionID;
public SessionClavardage(Socket link, ChatApp app) {
this.setLink(link);
this.setApp(app);
try {
this.setU2(app.getActifUsers().getIPList(link.getInetAddress()));
this.setOut(new ObjectOutputStream(link.getOutputStream()));
this.setIn(new ObjectInputStream(link.getInputStream()));
}catch(Exception e) {
e.getStackTrace();
}
this.derniersMsg = new ArrayList<MessageHorodate>();
this.SessionID = 2;
Platform.runLater( () ->
new FenetreSession(this)
);
this.pcs = new PropertyChangeSupport(this);
this.start();
}
public SessionClavardage(Utilisateur u2, ChatApp app) {
this.setU2(u2);
this.setApp(app);
try {
Socket s = new Socket(u2.getIp(),5000);
this.setOut(new ObjectOutputStream(s.getOutputStream()));
this.setIn(new ObjectInputStream(s.getInputStream()));
this.setLink(s);
} catch (IOException e) {
e.printStackTrace();
}
this.derniersMsg = new ArrayList<MessageHorodate>();
this.pcs = new PropertyChangeSupport(this);
this.app.getDb().CreationTableHistorique("Doudou","Marvel");
this.start();
Platform.runLater( () ->
new FenetreSession(this)
);
}
public void addPropertyChangeListener(PropertyChangeListener pcl){
this.pcs.addPropertyChangeListener("MessageRecu",pcl);
this.pcs.addPropertyChangeListener("FinDeLaSession",pcl);
}
public void arretSession() {
MessageHorodate msgh = new MessageHorodate(getU2(),getApp().getMe(),".",2);
try {
getOut().writeObject(msgh.toString());
} catch (IOException e) {
//e.printStackTrace();
}
finally {
try {
link.close();
} catch (IOException e) {
}
}
}
public void envoiMsg(String msg) {
MessageHorodate msgh = new MessageHorodate(getU2(),getApp().getMe(),msg,1);
try {
getOut().writeObject(msgh.toString());
app.getDb().ajoutHistorique(u2.getId(), app.getMe().getId(),msg);
} catch (IOException e) {
e.printStackTrace();
}
}
public MessageHorodate getDernierMsg() {
return this.derniersMsg.remove(0);
}
public void run() {
String plaintext = null;
MessageHorodate msg = null;
System.out.println("Session demarre");
app.getDb().CreationTableHistorique(app.getMe().getId(), u2.getId());
while(true) {
try {
plaintext = (String) getIn().readObject();
msg = MessageHorodate.stringToMessageHorodate(plaintext);
} catch (ClassNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
pcs.firePropertyChange("FinDeLaSession", false, true);
break;
}
if(msg.getType() == 2) {
pcs.firePropertyChange("FinDeLaSession", false, true);
try {
link.close();
} catch (IOException e) {
break;
}
break;
}
derniersMsg.add(msg);
pcs.firePropertyChange("MessageRecu",false,true);
}
}
public ObjectOutputStream getOut() {
return out;
}
public void setOut(ObjectOutputStream out) {
this.out = out;
}
public ObjectInputStream getIn() {
return in;
}
public void setIn(ObjectInputStream in) {
this.in = in;
}
public Socket getLink() {
return link;
}
public void setLink(Socket link) {
this.link = link;
}
public ChatApp getApp() {
return app;
}
public void setApp(ChatApp app) {
this.app = app;
}
public Utilisateur getU2() {
return u2;
}
public void setU2(Utilisateur u2) {
this.u2 = u2;
}
public int getSessionID() {
return SessionID;
}
public void setSessionID(int sessionID) {
SessionID = sessionID;
}
}

View file

@ -0,0 +1,365 @@
package chatapp.Protocol;
import java.io.IOException;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.InetAddress;
import java.net.NetworkInterface;
import java.net.SocketException;
import java.net.Inet4Address;
import java.util.ArrayList;
import java.util.Enumeration;
import java.util.List;
import java.util.Objects;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import chatapp.Controller.*;
import chatapp.Model.*;
/**
* <p>
* Classe representant les echanges UDP entre utilisateurs.
* </p>
*/
public class UDPEchange {
private static Boolean Connecte = true;
// True si l'utilisateur peut se connecter avec ce nom d'utilisateur , False sinon
private static Boolean EcouteEnCours = false;
/**
* Getter
* @return le boolean connecte (True s'il peut se connecter avec ce nom d'utilisateur , False sinon)
*/
public static Boolean getConnecte() {
return Connecte;
}
/**
* Setter
* @param value La nouvelle valeur du boolean de connexion
*/
public static void setConnecte(Boolean value) {
Connecte = value ;
}
private static Boolean PseudoValide = true;
// True si l'utilisateur a (ou demande) un pseudo valide , False sinon
/**
* Getter
* @return le boolean PseudoValide (True s'il peut utiliser ce pseudo , False sinon)
*/
public static Boolean getPseudoValide() {
return PseudoValide;
}
/**
* Setter
* @param value La nouvelle valeur du boolean concernant le pseudo valide
*/
public static void setPseudoValide(Boolean value) {
PseudoValide = value ;
}
/**<p>
* Permet de recuperer l'adresse de l'hote sur le reseau au format IPv4.
* Si plusieurs adresses sont disponibles (plusieurs cartes réseaux), choisit la premiere trouvee
* </p>
* @return l'adresse IP au format IPv4
*/
public static InetAddress getCurrentIp() {
try {
Enumeration<NetworkInterface> networkInterfaces = NetworkInterface
.getNetworkInterfaces();
while (networkInterfaces.hasMoreElements()) {
NetworkInterface ni = (NetworkInterface) networkInterfaces
.nextElement();
Enumeration<InetAddress> nias = ni.getInetAddresses();
while(nias.hasMoreElements()) {
InetAddress ia= (InetAddress) nias.nextElement();
if (!ia.isLinkLocalAddress()
&& !ia.isLoopbackAddress()
&& ia instanceof Inet4Address) {
return ia;
}
}
}
} catch (Exception e) {
System.out.println("unable to get current IP " + e.getMessage());
}
return null;
}
/**
* <p>
* ©thode permettant d'envoyer un message à tout les utilisateurs
* a l'aide du protocole UDP
* </p>
* @param broadcastMessage correspond au message a transmettre aux utilisateurs
*/
public static void EnvoiBroadcast(String broadcastMessage) throws IOException {
int port = 1234 ;
// Envoie en broadcast à tous les utilsateurs
for (InetAddress broadcastAddr : listAllBroadcastAddresses()) {
DatagramSocket socket = new DatagramSocket();
socket.setBroadcast(true);
byte[]buffer = broadcastMessage.getBytes();
DatagramPacket packet = new DatagramPacket( buffer, buffer.length, broadcastAddr,port);
socket.send(packet);
socket.close();
System.out.println("Broadcast sent with address " + broadcastAddr.toString());
System.out.println("***********Message envoye***********");
System.out.println("Dest Ip: " + broadcastAddr.toString());
System.out.println("Dest port: " + String.valueOf(port));
System.out.println("Contenu: ");
System.out.println(broadcastMessage);
System.out.println("************************************");
}
}
/**
* <p>
* Methode permettant la reception de messages d'utilisateurs
* a l'aide du protocole UDP
* </p>
* @param app L'application de chat de l'utilisateur qui receptionne le message
*/
public static void ecouteUDP(ChatApp app)
{
DatagramSocket socket = null;
ExecutorService exec = Executors.newFixedThreadPool(1000);
try {
socket = new DatagramSocket(1234);
} catch (SocketException e1) {
e1.printStackTrace();
}
byte buffer[] = new byte[1024];
System.out.println("Ecoute sur le port: 1234");
while(true)
{
DatagramPacket data = new DatagramPacket(buffer,buffer.length);
try {
socket.receive(data);
} catch (IOException e) {
e.printStackTrace();
}
// Un thread est lance à chaque reception d'un message
System.out.println("Message recu!");
exec.submit(new RunnerUDP(data,app));
}
}
/**
* <p>
* Methode permettant d'envoyer un message a utilisateur en particulier
* a l'aide du protocole UDP
* </p>
* @param Adress l'addresse de l'utilisateur
* @param Message correspond au message à transmettre a l'utilisateur
*/
public static void envoiUnicast( InetAddress Adress , String Message ) throws IOException {
DatagramSocket socket = new DatagramSocket();
byte[]buffer = Message.getBytes();
DatagramPacket packet = new DatagramPacket( buffer, buffer.length, Adress, 1234 );
socket.send(packet);
socket.close();
System.out.println("***********Message envoye***********");
System.out.println("Dest Ip: " + Adress.toString());
System.out.println("Dest port: " + String.valueOf(1234));
System.out.println("Contenu: ");
System.out.println(Message);
System.out.println("************************************");
}
/**
* <p>
* Methode permettant de recuperer la liste des adresses de broadcast, chacune associer à une interface de la machine
* </p>
*/
static List<InetAddress> listAllBroadcastAddresses() throws SocketException {
List<InetAddress> broadcastList = new ArrayList<>();
Enumeration<NetworkInterface> interfaces
= NetworkInterface.getNetworkInterfaces();
while (interfaces.hasMoreElements()) {
NetworkInterface networkInterface = interfaces.nextElement();
if (networkInterface.isLoopback() || !networkInterface.isUp()) {
continue;
}
networkInterface.getInterfaceAddresses().stream()
.map(a -> a.getBroadcast())
.filter(Objects::nonNull)
.forEach(broadcastList::add);
}
return broadcastList;
}
}
/**
* <p>
* Classe implementant l'interface Runnable.
* Contient les traitements a executer dans un thread lancer par des methodes de la class UDPEchange
* </p>
*/
class RunnerUDP implements Runnable {
final DatagramPacket data ;
ChatApp app ;
public RunnerUDP(DatagramPacket data, ChatApp app) {
this.data= data;
this.app = app ;
}
/**
* <p>
* Methode qui redefinie les traitements qui seront executes dans le thread:
* Met à jour la liste des utilisateurs actifs
* </p>
*
*/
@Override
public void run() {
System.out.println("Thread started");
String received = new String(data.getData(), 0, data.getLength());
System.out.println("***********Message recu***********");
System.out.println(received);
System.out.println("**********************************");
String Type = received.split("\n")[0];
//****************************************************************************************************
//****************************************************************************************************
//****************************************Demande de connexion****************************************
//****************************************************************************************************
//****************************************
if (Type.equals("Connexion")) { // un utilisateur vient d'arriver sur le reseau
System.out.println("Reception d'une demande de connexion");
Utilisateur u = Utilisateur.stringToUtilisateur(received.split("\n")[1]);
if (! u.equals(this.app.getMe())) { // On envoit en broadcast mais on ne souhaite pas recevoir de message de nous même
String reponse = "Reponse Connexion\n";
if (!( app.getActifUsers() ).verifierUnicite(u.getPseudo())) {
System.out.println("Pseudo deja present dans la liste");
reponse += "false\n";
}
else {
System.out.println("Ajout d'un nouvel utilisateur dans la liste des Utilisateurs");
( app.getActifUsers() ).addList(u);
reponse += "true\n";
}
reponse += app.getMe().toString();
try {
UDPEchange.envoiUnicast(u.getIp(),reponse);
}catch(IOException e)
{
System.out.println("Echec de l'envoi du message");
}
( app.getActifUsers() ).afficherListeUtilisateurs();
}
}
//*******************************************************************************************************
//*******************************************************************************************************
//****************************************Reponse d'une connexion****************************************
//*******************************************************************************************************
//*******************************************************************************************************
if (Type.equals("Reponse Connexion")) { // Un utilisateur te repond suite à ta demande de connexion
if((received.split("\n")[1]).equals("true")) {
Utilisateur u = Utilisateur.stringToUtilisateur(received.split("\n")[2]);
app.getActifUsers().addList(u);
app.getActifUsers().afficherListeUtilisateurs();
}
else {
System.out.println("Pseudo deja pris");
UDPEchange.setConnecte(false);
}
}
//*******************************************************************************************************************
//*******************************************************************************************************************
//****************************************Demande de modification d'un pseudo****************************************
//*******************************************************************************************************************
//*******************************************************************************************************************
if (Type.equals("Demande Modification Pseudo")) {
Utilisateur Source = Utilisateur.stringToUtilisateur(received.split("\n")[1]);
if (! Source.equals(this.app.getMe())) { // On envoit en broadcast mais on ne souhaite pas recevoir de message de nous même
String nouveau = received.split("\n")[2] ;
String Message = "";
if(( app.getActifUsers() ).verifierUnicite(nouveau)) {
Message = "Bon Choix Pseudo\n" + nouveau ;
}
else {
Message = "Mauvais Choix Pseudo\n" ;
}
System.out.println(Message);
try {
UDPEchange.envoiUnicast(Source.getIp(),Message);
} catch (IOException e) {
e.printStackTrace();
}
}
}
//************************************************************************************************************
//************************************************************************************************************
//**************************************** Modification pseudo reussi ****************************************
//************************************************************************************************************
//************************************************************************************************************
if (Type.equals("Modification pseudo reussi")) {
Utilisateur Source = Utilisateur.stringToUtilisateur(received.split("\n")[1]);
if (! Source.equals(this.app.getMe())) { // On envoit en broadcast mais on ne souhaite pas recevoir de message de nous même
String nouveau = received.split("\n")[2] ;
if(app.getActifUsers().appartient(Source)) { // On verifie d'abord que Source appartient bien a la liste des utilisateurs actifs
app.getActifUsers().modifierList(Source.getPseudo(), nouveau);
}
{
// Suite a une perte d'un message lors d'une connexion l'utilisateur Source n'apparait pas dans la liste
app.getActifUsers().addList(Source);
}
}
}
//*********************************************************************************************************
//*********************************************************************************************************
//****************************************Mauvais choix d'un pseudo****************************************
//*********************************************************************************************************
//*********************************************************************************************************
if (Type.equals("Mauvais Choix Pseudo")) {
System.out.println("Ce choix de pseudo est déjà pris il te faut en choisir un autre");
UDPEchange.setPseudoValide(false);
}
//******************************************************************************************************************
//******************************************************************************************************************
//****************************************Bon choix d'un pseudo*****************************************************
//******************************************************************************************************************
//******************************************************************************************************************
if (Type.equals("Bon Choix Pseudo")) {
// Il n'y a rien a faire ici
}
//*********************************************************************************************************
//*********************************************************************************************************
//****************************************Demande d'une deconnexion****************************************
//*********************************************************************************************************
//*********************************************************************************************************
if (Type.equals("Deconnexion")) {
( app.getActifUsers() ).supprimerList(Utilisateur.stringToUtilisateur(received.split("\n")[1]));
}
}
}

View file

@ -0,0 +1,99 @@
package chatapp.View;
import java.io.IOException;
import java.net.URL;
import java.util.ResourceBundle;
import chatapp.Controller.ChatApp;
import javafx.event.ActionEvent;
import javafx.fxml.FXML;
import javafx.fxml.FXMLLoader;
import javafx.scene.Parent;
import javafx.scene.Scene;
import javafx.scene.control.Alert;
import javafx.scene.control.Button;
import javafx.scene.control.TextField;
import javafx.scene.text.Text;
import javafx.stage.Stage;
public class ChangementPseudo {
@FXML // ResourceBundle that was given to the FXMLLoader
private ResourceBundle resources;
@FXML // URL location of the FXML file that was given to the FXMLLoader
private URL location;
@FXML // fx:id="validationButton"
private Button validationButton; // Value injected by FXMLLoader
@FXML // fx:id="pseudonyme"
private TextField pseudonyme; // Value injected by FXMLLoader
@FXML // fx:id="pseudonyme1"
private Text pseudonyme1; // Value injected by FXMLLoader
@FXML // fx:id="MenuButton"
private Button MenuButton; // Value injected by FXMLLoader
private ChatApp chatApp;
@FXML
void nouveauPseudo(ActionEvent event) {
}
@FXML
/**
* <p> Handler permettant de retourner au menu principal sur pression du MenuButton</p>
*/
void retourMenu(ActionEvent event) {
System.out.println("Retour au menu principal");
Stage stage = (Stage) MenuButton.getScene().getWindow();
Parent root = null;
try {
root = FXMLLoader.load(getClass().getResource("/fenetres/View_Menu.fxml"));
} catch (IOException e) {
e.printStackTrace();
}
Scene scene = new Scene(root);
stage.setScene(scene);
stage.show();
}
@FXML
/**
* <p> Handler permettant de lancer la verrification de l'unicite du ppseudo sur pression du validtionButton</p>
*/
void validerPseudo(ActionEvent event) {
boolean pseudoOK = false;
try {
pseudoOK = chatApp.modifierPseudo(pseudonyme.getText());
} catch (IOException e) {
e.printStackTrace();
}
if(pseudoOK){
this.retourMenu(null);
}
else{
Alert alert = new Alert(Alert.AlertType.INFORMATION);
alert.setTitle("Changement pseudo");
// Header Text: null
alert.setHeaderText(null);
alert.setContentText("Echec de Connexion: le pseudo "+pseudonyme.getText()+" est deja pris");
alert.showAndWait();
}
}
/**
* <p> Initialization de la classe ChangementPseudo et permet d'initialiser les parametres</p>
*/
@FXML // This method is called by the FXMLLoader when initialization is complete
void initialize() {
chatApp = ChatApp.getInstance();
pseudonyme1.setText(chatApp.getMe().getPseudo());
this.validationButton.setDefaultButton(true);
//System.out.println(this.validationButton.isDefaultButton());
}
}

View file

@ -0,0 +1,139 @@
package chatapp.View;
import java.beans.PropertyChangeEvent;
import java.beans.PropertyChangeListener;
import java.net.URL;
import java.text.DateFormat;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.ResourceBundle;
import chatapp.Controller.ChatApp;
import chatapp.Model.MessageHorodate;
import chatapp.Model.Utilisateur;
import chatapp.Protocol.SessionClavardage;
import javafx.application.Platform;
import javafx.event.ActionEvent;
import javafx.fxml.FXML;
import javafx.fxml.Initializable;
import javafx.scene.control.Button;
import javafx.scene.control.TextArea;
import javafx.scene.control.TextField;
import javafx.scene.text.Text;
import javafx.stage.Stage;
public class Clavardage implements Initializable, PropertyChangeListener {
@FXML //fx:id="plusButton"
public Button plusButton;
@FXML // ResourceBundle that was given to the FXMLLoader
private ResourceBundle resources;
@FXML // URL location of the FXML file that was given to the FXMLLoader
private URL location;
@FXML // fx:id="AEnvoyer"
private TextField AEnvoyer; // Value injected by FXMLLoader
@FXML // fx:id="EnvoyerButton"
private Button EnvoyerButton; // Value injected by FXMLLoader
@FXML // fx:id="pseudonyme1"
private Text pseudonyme1; // Value injected by FXMLLoader
@FXML // fx:id="ChatText"
private TextArea ChatText; // Value injected by FXMLLoader
@FXML // fx:id="MenuButton"
private Utilisateur u2;
private SessionClavardage session;
private String nomTable;
@FXML
/**
* <p>Handler gerant l'envoi du message contenu dans le TextField AEnvoyer et sur pression du bouton EnvoyerButton</p>
*/
void envoyerMessage(ActionEvent event) {
String msg = AEnvoyer.getText();
AEnvoyer.clear();
if(!msg.equals("")) {
session.envoiMsg(msg);
Date d = new Date();
DateFormat format = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss:0");
msg = "Moi (" + format.format(d).toString() + ") : " + msg + "\n";
ChatText.appendText(msg);
}
}
/**
* Setter
* @param session la session a associer a la classe
*/
public void setSession(SessionClavardage session) {
this.session = session;
this.session.addPropertyChangeListener(this);
this.u2=session.getU2();
this.pseudonyme1.setText(u2.getPseudo());
}
/**
* <p>Handler des differents evenements auxquels s'est abonne le PropertyChangeListener
* La classe est informee lorsque la session recoit un message ou lorsque la session se termine </p>
* @param evt l'evenement informe par le pcs
*/
@Override
public void propertyChange(PropertyChangeEvent evt) {
switch (evt.getPropertyName()){
case "MessageRecu" :
MessageHorodate msgh = session.getDernierMsg();
DateFormat format = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss:0");
Date d = new Date();
String msg = u2.getPseudo();
msg += " ("+ format.format(d).toString() +") ";
msg+=": "+msgh.getMessage();
ChatText.appendText(msg);
break;
case "FinDeLaSession" :
this.session.arretSession();
Platform.runLater(new Runnable() {
@Override
public void run() {
Stage stage = (Stage) AEnvoyer.getScene().getWindow();
stage.close();
}
});
}
}
public SessionClavardage getSession(){
return session;
}
/**
* Permet d'initialiser les differents parametres de la classe
* @param location
* @param resources
*/
@Override
public void initialize(URL location, ResourceBundle resources) {
EnvoyerButton.setDefaultButton(true);
this.ChatText.setEditable(false);
}
/**
* <p> Permet de recepurer plus de messages stoces dans la database en appuyant sur le bouton plusButton</p>
* @param actionEvent
*/
public void ajouterMessagesHistorique(ActionEvent actionEvent) {
this.nomTable = this.session.getApp().getDb().getNomTable(u2,this.session.getApp().getMe());
String historique = this.session.getApp().getDb().recupNMsg(session.getApp().getMe().getId(),this.u2.getId(), this.session.getApp().getDb().tailleBDD("Chat_mbp-de-auriane.home_mbp-de-auriane.home"));
ChatText.clear();
ChatText.insertText(0,historique);
}
}

View file

@ -0,0 +1,70 @@
package chatapp.View;
import java.io.IOException;
import java.net.URL;
import java.util.ResourceBundle;
import chatapp.Controller.ChatApp;
import javafx.event.ActionEvent;
import javafx.fxml.FXML;
import javafx.fxml.FXMLLoader;
import javafx.scene.Parent;
import javafx.scene.Scene;
import javafx.scene.control.Alert;
import javafx.scene.control.Button;
import javafx.scene.control.TextField;
import javafx.stage.Stage;
public class ConnexionScreen {
public Button connexionButton;
public TextField pseudonyme;
@FXML // ResourceBundle that was given to the FXMLLoader
private ResourceBundle resources;
@FXML // URL location of the FXML file that was given to the FXMLLoader
private URL location;
@FXML // This method is called by the FXMLLoader when initialization is complete
void initialize() {
connexionButton.setDefaultButton(true);
}
/**
* <p>Handler permettant de lancer la connexion avec le pseudonyme contenu dans le TextField pseudonyme en appuyant sur le connexionButton
* </p>
* @param actionEvent
*/
public void connexion(ActionEvent actionEvent) {
Boolean connexion = false;
try {
connexion = ChatApp.getInstance().connexion(pseudonyme.getText());
} catch (IOException e) {
e.printStackTrace();
}
if(!connexion){
Alert alert = new Alert(Alert.AlertType.INFORMATION);
alert.setTitle("Connexion");
// Header Text: null
alert.setHeaderText(null);
alert.setContentText("Echec de Connexion: le pseudo "+pseudonyme.getText()+" est deja pris");
alert.showAndWait();
}
else{
Stage stage = (Stage) connexionButton.getScene().getWindow();
Parent root = null;
try {
root = FXMLLoader.load(getClass().getResource("/fenetres/View_Menu.fxml"));
} catch (IOException e) {
e.printStackTrace();
}
Scene scene = new Scene(root);
stage.setScene(scene);
stage.show();
}
}
}

View file

@ -0,0 +1,77 @@
/**
* Sample Skeleton for 'View_Demarrer_Session.fxml' Controller Class
*/
package chatapp.View;
import java.io.IOException;
import java.net.URL;
import java.util.ResourceBundle;
import chatapp.Controller.ChatApp;
import chatapp.Model.ListUtilisateurs;
import chatapp.Model.Utilisateur;
import chatapp.Protocol.RunnerEcouteTCP;
import javafx.event.ActionEvent;
import javafx.fxml.FXML;
import javafx.fxml.FXMLLoader;
import javafx.scene.Parent;
import javafx.scene.Scene;
import javafx.scene.control.Button;
import javafx.scene.control.ComboBox;
import javafx.stage.Stage;
public class DemarrerSession {
@FXML // ResourceBundle that was given to the FXMLLoader
private ResourceBundle resources;
@FXML // URL location of the FXML file that was given to the FXMLLoader
private URL location;
@FXML // fx:id="choixContact"
private ComboBox<String> choixContact; // Value injected by FXMLLoader
@FXML // fx:id="MenuButton"
private Button MenuButton; // Value injected by FXMLLoader
private ChatApp chatApp;
/**
* <p> Handler permettant de demarrer une session de clavardage avec le contact choisi dans la comboBox choixContaact</p>
* @param event
*/
@FXML
void demarrerSessionAvec(ActionEvent event) {
chatApp.demarrerSession(choixContact.getValue());
}
/**
* <p> Handler permettant de retourner au menu principal sur pression du MenuButton</p>
*/
@FXML
void retourMenu(ActionEvent event) {
Stage stage = (Stage) MenuButton.getScene().getWindow();
Parent root = null;
try {
root = FXMLLoader.load(getClass().getResource("/fenetres/View_Menu.fxml"));
} catch (IOException e) {
e.printStackTrace();
}
Scene scene = new Scene(root);
stage.setScene(scene);
stage.show();
}
/**
* <p> Initialization de la classe ChangementPseudo et permet d'initialiser les parametres</p>
*/
@FXML // This method is called by the FXMLLoader when initialization is complete
void initialize() {
this.chatApp = ChatApp.getInstance();
ListUtilisateurs utils = chatApp.getActifUsers();
for(Utilisateur u : utils.getActifUsers()){
choixContact.getItems().add(u.getPseudo());
}
}
}

View file

@ -0,0 +1,46 @@
package chatapp.View;
import chatapp.Protocol.SessionClavardage;
import javafx.event.EventHandler;
import javafx.fxml.FXMLLoader;
import javafx.scene.Parent;
import javafx.scene.Scene;
import javafx.stage.Stage;
import javafx.stage.WindowEvent;
import java.beans.PropertyChangeListener;
import java.io.IOException;
public class FenetreSession extends Stage {
SessionClavardage session;
/**
* <p> Permet l'ouverture de la fenetre associee a la session de clavardage</p>
*/
public FenetreSession(SessionClavardage session) {
FXMLLoader fichier = new FXMLLoader(getClass().getResource("/fenetres/View_Clavardage.fxml"));
try{
Parent rootchat = fichier.load();
Clavardage controller = fichier.getController();
System.out.println("Session id "+session.getSessionID());
//controller.printsalut();
controller.setSession(session);
Scene scene1 = null;
scene1 = new Scene(rootchat,600,400);
this.setScene(scene1);
this.setTitle("Session avec "+session.getU2().getPseudo());
this.setMinWidth(600);
this.setMinHeight(400);
//this.setMaxWidth(600);
//this.setMaxHeight(400);
this.show();
this.centerOnScreen();
this.setOnCloseRequest(new EventHandler<WindowEvent>() {
public void handle(WindowEvent we) {
session.arretSession();
}
});
} catch (Exception e) {
e.printStackTrace();
}
}
}

View file

@ -0,0 +1,105 @@
package chatapp.View;
import java.io.IOException;
import java.net.URL;
import java.util.ResourceBundle;
import chatapp.Controller.ChatApp;
import javafx.application.Platform;
import javafx.event.ActionEvent;
import javafx.fxml.FXML;
import javafx.fxml.FXMLLoader;
import javafx.scene.Parent;
import javafx.scene.Scene;
import javafx.scene.control.MenuItem;
import javafx.scene.text.Text;
import javafx.stage.Stage;
public class View_Menu {
public Text pseudonyme;
public MenuItem utilsActifsButton;
public MenuItem demarrerSessionButton;
public MenuItem changerPseudoButton;
@FXML // ResourceBundle that was given to the FXMLLoader
private ResourceBundle resources;
private ChatApp chatapp;
@FXML // URL location of the FXML file that was given to the FXMLLoader
private URL location;
@FXML // This method is called by the FXMLLoader when initialization is complete
void initialize() {
this.chatapp = ChatApp.getInstance();
this.pseudonyme.setText(this.chatapp.getMe().getPseudo());
}
/**
* <p>Handler permettant d'aller a la scene View_Utilisateurs pour afficher la liste des utilisateurs actifs</p>
* @param actionEvent
*/
public void afficherUtilsActifs(ActionEvent actionEvent) {
Stage stage = (Stage) pseudonyme.getScene().getWindow();
Parent root = null;
try {
root = FXMLLoader.load(getClass().getResource("/fenetres/View_Utilisateurs.fxml"));
} catch (IOException e) {
e.printStackTrace();
}
Scene scene = new Scene(root);
stage.setScene(scene);
stage.show();
}
/**
* <p>Handler permettant d'aller a la scene Demarrer_Session pour choisir un utilisateur avec qui clavarder
* @param actionEvent
*/
public void demarrerSession(ActionEvent actionEvent) {
Stage stage = (Stage) pseudonyme.getScene().getWindow();
Parent root = null;
try {
root = FXMLLoader.load(getClass().getResource("/fenetres/View_Demarrer_Session.fxml"));
} catch (IOException e) {
e.printStackTrace();
}
Scene scene = new Scene(root);
stage.setScene(scene);
stage.show();
}
/**
* <p>Handler permettant d'aller a la scene View_ChangementPseudo pour changer son pseudonyme
* @param actionEvent
*/
public void changerPseudo(ActionEvent actionEvent) {
Stage stage = (Stage) pseudonyme.getScene().getWindow();
Parent root = null;
try {
root = FXMLLoader.load(getClass().getResource("/fenetres/View_ChangementPseudo.fxml"));
} catch (IOException e) {
e.printStackTrace();
}
Scene scene = new Scene(root);
stage.setScene(scene);
stage.show();
}
/**
* <p>Handler permettant de se deconnecter et fermer l'application
* @param actionEvent
*/
public void deconnexion(ActionEvent actionEvent) {
try {
chatapp.deconnexion();
/*chatapp.getMain().stop();
Platform.exit();
System.exit(0);*/
} catch (IOException e) {
e.printStackTrace();
} catch (Exception e) {
e.printStackTrace();
}
}
}

View file

@ -0,0 +1,57 @@
package chatapp.View;
import java.io.IOException;
import java.net.URL;
import java.util.ResourceBundle;
import chatapp.Controller.ChatApp;
import chatapp.Model.ListUtilisateurs;
import chatapp.Model.Utilisateur;
import javafx.event.ActionEvent;
import javafx.fxml.FXML;
import javafx.fxml.FXMLLoader;
import javafx.scene.Parent;
import javafx.scene.Scene;
import javafx.scene.control.Button;
import javafx.scene.control.TextArea;
import javafx.stage.Stage;
public class View_Utilisateurs {
public TextArea ListeUtilisateurs;
public Button MenuButton;
@FXML // ResourceBundle that was given to the FXMLLoader
private ResourceBundle resources;
@FXML // URL location of the FXML file that was given to the FXMLLoader
private URL location;
@FXML // This method is called by the FXMLLoader when initialization is complete
void initialize() {
ListUtilisateurs utilisateurs = ChatApp.getInstance().getActifUsers();
ListeUtilisateurs.setText("");
for(Utilisateur elem : utilisateurs.getActifUsers()) {
ListeUtilisateurs.appendText( " - " +elem.getPseudo() + '\n');
}
ListeUtilisateurs.setEditable(false);
}
/**
* <p> Handler permettant de retourner au menu principal sur pression du MenuButton</p>
*/
public void retourMenu(ActionEvent actionEvent) {
Stage stage = (Stage) MenuButton.getScene().getWindow();
Parent root = null;
try {
root = FXMLLoader.load(getClass().getResource("/fenetres/View_Menu.fxml"));
} catch (IOException e) {
e.printStackTrace();
}
Scene scene = new Scene(root);
stage.setScene(scene);
stage.show();
}
}

View file

@ -0,0 +1,53 @@
<?xml version="1.0" encoding="UTF-8"?>
<?import javafx.scene.control.Button?>
<?import javafx.scene.control.TextField?>
<?import javafx.scene.layout.AnchorPane?>
<?import javafx.scene.layout.ColumnConstraints?>
<?import javafx.scene.layout.GridPane?>
<?import javafx.scene.layout.HBox?>
<?import javafx.scene.layout.RowConstraints?>
<?import javafx.scene.layout.VBox?>
<?import javafx.scene.text.Font?>
<?import javafx.scene.text.Text?>
<AnchorPane maxHeight="-Infinity" maxWidth="-Infinity" minHeight="-Infinity" minWidth="-Infinity" prefHeight="400.0" prefWidth="600.0" xmlns="http://javafx.com/javafx/11.0.1" xmlns:fx="http://javafx.com/fxml/1" fx:controller="chatapp.View.ConnexionScreen">
<children>
<VBox prefHeight="400.0" prefWidth="600.0">
<children>
<HBox alignment="CENTER" prefHeight="100.0" prefWidth="200.0" style="-fx-background-color: #3299a8;">
<children>
<Text fill="#b0c926" strokeType="OUTSIDE" strokeWidth="0.0" text="ChatApp">
<font>
<Font name="OCR A Extended" size="48.0" />
</font>
</Text>
</children>
</HBox>
<HBox alignment="CENTER" prefHeight="304.0" prefWidth="600.0" style="-fx-background-color: #3299a8;">
<children>
<GridPane alignment="CENTER" prefHeight="302.0" prefWidth="279.0">
<columnConstraints>
<ColumnConstraints hgrow="SOMETIMES" minWidth="10.0" prefWidth="100.0" />
<ColumnConstraints hgrow="SOMETIMES" minWidth="10.0" prefWidth="100.0" />
</columnConstraints>
<rowConstraints>
<RowConstraints maxHeight="254.19998168945312" minHeight="10.0" prefHeight="123.19998779296876" vgrow="SOMETIMES" />
<RowConstraints maxHeight="217.80000152587894" minHeight="10.0" prefHeight="107.20001220703125" vgrow="SOMETIMES" />
</rowConstraints>
<children>
<TextField fx:id="pseudonyme" prefHeight="26.0" prefWidth="447.0" promptText="Pseudonyme" GridPane.columnSpan="2" />
<Button fx:id="connexionButton" alignment="CENTER" contentDisplay="CENTER" mnemonicParsing="false" onAction="#connexion" prefHeight="38.0" prefWidth="287.0" style="-fx-background-color: #b0c926;" text="Connexion" textFill="#3299a8" GridPane.columnSpan="2" GridPane.rowIndex="1">
<font>
<Font name="OCR A Extended" size="27.0" />
</font>
</Button>
</children>
</GridPane>
</children>
</HBox>
<HBox alignment="CENTER" layoutX="10.0" layoutY="10.0" prefHeight="0.0" prefWidth="600.0" style="-fx-background-color: #3299a8;" />
</children>
</VBox>
</children>
</AnchorPane>

View file

@ -0,0 +1,72 @@
<?xml version="1.0" encoding="UTF-8"?>
<?import javafx.scene.control.Button?>
<?import javafx.scene.control.TextField?>
<?import javafx.scene.layout.AnchorPane?>
<?import javafx.scene.layout.ColumnConstraints?>
<?import javafx.scene.layout.GridPane?>
<?import javafx.scene.layout.HBox?>
<?import javafx.scene.layout.RowConstraints?>
<?import javafx.scene.layout.VBox?>
<?import javafx.scene.text.Font?>
<?import javafx.scene.text.Text?>
<AnchorPane maxHeight="-Infinity" maxWidth="-Infinity" minHeight="-Infinity" minWidth="-Infinity" prefHeight="400.0" prefWidth="600.0" xmlns="http://javafx.com/javafx/11.0.1" xmlns:fx="http://javafx.com/fxml/1" fx:controller="chatapp.View.ChangementPseudo">
<children>
<VBox prefHeight="400.0" prefWidth="600.0">
<children>
<HBox alignment="CENTER" prefHeight="100.0" prefWidth="200.0" style="-fx-background-color: #3299a8;">
<children>
<Text fill="#b0c926" strokeType="OUTSIDE" strokeWidth="0.0" text="Changement Pseudo">
<font>
<Font name="OCR A Extended" size="48.0" />
</font>
</Text>
</children>
</HBox>
<HBox alignment="CENTER" prefHeight="304.0" prefWidth="600.0" style="-fx-background-color: #3299a8;">
<children>
<GridPane>
<columnConstraints>
<ColumnConstraints hgrow="SOMETIMES" minWidth="10.0" prefWidth="100.0" />
<ColumnConstraints hgrow="SOMETIMES" minWidth="10.0" prefWidth="100.0" />
</columnConstraints>
<rowConstraints>
<RowConstraints minHeight="10.0" prefHeight="30.0" vgrow="SOMETIMES" />
<RowConstraints minHeight="10.0" prefHeight="30.0" vgrow="SOMETIMES" />
<RowConstraints minHeight="10.0" prefHeight="30.0" vgrow="SOMETIMES" />
</rowConstraints>
<children>
<Button fx:id="validationButton" alignment="CENTER" contentDisplay="CENTER" mnemonicParsing="false" onAction="#validerPseudo" prefHeight="38.0" prefWidth="287.0" style="-fx-background-color: #b0c926;" text="Valider" textFill="#3299a8" GridPane.columnSpan="2" GridPane.rowIndex="2">
<font>
<Font name="OCR A Extended" size="27.0" />
</font>
</Button>
<TextField fx:id="pseudonyme" prefHeight="26.0" prefWidth="447.0" promptText="Pseudonyme" GridPane.columnSpan="2" GridPane.rowIndex="1" />
<Text fill="#b0c926" strokeType="OUTSIDE" strokeWidth="0.0" text="Ancien :">
<font>
<Font size="19.0" />
</font>
</Text>
<Text fx:id="pseudonyme1" fill="WHITE" strokeType="OUTSIDE" strokeWidth="0.0" text="Pseudo" GridPane.columnIndex="1">
<font>
<Font size="19.0" />
</font>
</Text>
</children>
</GridPane>
</children>
</HBox>
<HBox alignment="BOTTOM_RIGHT" prefHeight="63.0" prefWidth="600.0" style="-fx-background-color: #3299a8;">
<children>
<Button fx:id="MenuButton" alignment="CENTER" mnemonicParsing="false" onAction="#retourMenu" style="-fx-background-color: #b0c926;" text="Retour au menu" textFill="WHITE">
<font>
<Font name="OCR A Extended" size="18.0" />
</font>
</Button>
</children>
</HBox>
</children>
</VBox>
</children>
</AnchorPane>

View file

@ -0,0 +1,90 @@
<?xml version="1.0" encoding="UTF-8"?>
<?import javafx.scene.control.Button?>
<?import javafx.scene.control.TextArea?>
<?import javafx.scene.control.TextField?>
<?import javafx.scene.layout.AnchorPane?>
<?import javafx.scene.layout.ColumnConstraints?>
<?import javafx.scene.layout.GridPane?>
<?import javafx.scene.layout.HBox?>
<?import javafx.scene.layout.RowConstraints?>
<?import javafx.scene.layout.VBox?>
<?import javafx.scene.text.Font?>
<?import javafx.scene.text.Text?>
<AnchorPane maxHeight="-Infinity" maxWidth="-Infinity" minHeight="-Infinity" minWidth="-Infinity" prefHeight="400.0" prefWidth="600.0" xmlns="http://javafx.com/javafx/11.0.1" xmlns:fx="http://javafx.com/fxml/1" fx:controller="chatapp.View.Clavardage">
<children>
<VBox prefHeight="400.0" prefWidth="600.0">
<children>
<HBox alignment="CENTER" prefHeight="100.0" prefWidth="200.0" style="-fx-background-color: #3299a8;">
<children>
<Text fill="#b0c926" strokeType="OUTSIDE" strokeWidth="0.0" text="Session de Clavardage">
<font>
<Font name="OCR A Extended" size="48.0" />
</font>
</Text>
</children>
</HBox>
<HBox alignment="CENTER" prefHeight="304.0" prefWidth="600.0" style="-fx-background-color: #3299a8;">
<children>
<GridPane prefHeight="282.0" prefWidth="402.0">
<columnConstraints>
<ColumnConstraints hgrow="SOMETIMES" minWidth="10.0" prefWidth="100.0" />
</columnConstraints>
<rowConstraints>
<RowConstraints maxHeight="257.0" minHeight="10.0" prefHeight="44.0" vgrow="NEVER" />
<RowConstraints maxHeight="257.0" minHeight="10.0" prefHeight="228.0" vgrow="NEVER" />
<RowConstraints maxHeight="257.0" minHeight="10.0" prefHeight="42.0" vgrow="NEVER" />
</rowConstraints>
<children>
<GridPane GridPane.rowIndex="2">
<columnConstraints>
<ColumnConstraints hgrow="SOMETIMES" maxWidth="327.0" minWidth="10.0" prefWidth="327.0" />
<ColumnConstraints hgrow="SOMETIMES" maxWidth="156.0" minWidth="10.0" prefWidth="75.0" />
</columnConstraints>
<rowConstraints>
<RowConstraints />
<RowConstraints maxHeight="79.0" minHeight="0.0" prefHeight="60.0" vgrow="SOMETIMES" />
</rowConstraints>
<children>
<TextField fx:id="AEnvoyer" prefHeight="26.0" prefWidth="447.0" promptText="Enter Text" GridPane.rowIndex="1" />
<Button fx:id="EnvoyerButton" mnemonicParsing="false" onAction="#envoyerMessage" prefHeight="27.0" prefWidth="73.0" text="Envoyer" GridPane.columnIndex="1" GridPane.rowIndex="1" />
</children>
</GridPane>
<GridPane prefHeight="34.0" prefWidth="345.0">
<columnConstraints>
<ColumnConstraints hgrow="SOMETIMES" minWidth="10.0" prefWidth="100.0" />
<ColumnConstraints hgrow="SOMETIMES" minWidth="10.0" prefWidth="100.0" />
<ColumnConstraints halignment="RIGHT" hgrow="SOMETIMES" minWidth="10.0" prefWidth="100.0" />
</columnConstraints>
<rowConstraints>
<RowConstraints minHeight="10.0" prefHeight="30.0" vgrow="SOMETIMES" />
</rowConstraints>
<children>
<Text fill="#b0c926" strokeType="OUTSIDE" strokeWidth="0.0" text="Chat avec : ">
<font>
<Font size="19.0" />
</font>
</Text>
<Text fx:id="pseudonyme1" fill="WHITE" strokeType="OUTSIDE" strokeWidth="0.0" text="Pseudo" textAlignment="CENTER" wrappingWidth="133.16357421875" GridPane.columnIndex="1">
<font>
<Font size="19.0" />
</font>
</Text>
<Button fx:id="plusButton" mnemonicParsing="false" onAction="#ajouterMessagesHistorique" style="-fx-background-color: #b0c926;" text="+" textAlignment="RIGHT" textFill="WHITE" GridPane.columnIndex="2">
<font>
<Font name="OCR A Extended" size="16.0" />
</font>
</Button>
</children>
</GridPane>
<TextArea fx:id="ChatText" prefHeight="200.0" prefWidth="200.0" GridPane.rowIndex="1" />
</children>
</GridPane>
</children>
</HBox>
<HBox alignment="BOTTOM_RIGHT" prefHeight="63.0" prefWidth="600.0" style="-fx-background-color: #3299a8;" />
</children>
</VBox>
</children>
</AnchorPane>

View file

@ -0,0 +1,62 @@
<?xml version="1.0" encoding="UTF-8"?>
<?import javafx.scene.control.Button?>
<?import javafx.scene.control.ComboBox?>
<?import javafx.scene.layout.AnchorPane?>
<?import javafx.scene.layout.ColumnConstraints?>
<?import javafx.scene.layout.GridPane?>
<?import javafx.scene.layout.HBox?>
<?import javafx.scene.layout.RowConstraints?>
<?import javafx.scene.layout.VBox?>
<?import javafx.scene.text.Font?>
<?import javafx.scene.text.Text?>
<AnchorPane maxHeight="-Infinity" maxWidth="-Infinity" minHeight="-Infinity" minWidth="-Infinity" prefHeight="400.0" prefWidth="600.0" xmlns="http://javafx.com/javafx/11.0.1" xmlns:fx="http://javafx.com/fxml/1" fx:controller="chatapp.View.DemarrerSession">
<children>
<VBox prefHeight="400.0" prefWidth="600.0">
<children>
<HBox alignment="CENTER" prefHeight="100.0" prefWidth="200.0" style="-fx-background-color: #3299a8;">
<children>
<Text fill="#b0c926" strokeType="OUTSIDE" strokeWidth="0.0" text="Démarrer Session">
<font>
<Font name="OCR A Extended" size="48.0" />
</font>
</Text>
</children>
</HBox>
<HBox alignment="CENTER" prefHeight="304.0" prefWidth="600.0" style="-fx-background-color: #3299a8;">
<children>
<GridPane prefHeight="166.0" prefWidth="350.0">
<columnConstraints>
<ColumnConstraints hgrow="SOMETIMES" minWidth="10.0" prefWidth="100.0" />
<ColumnConstraints hgrow="SOMETIMES" minWidth="10.0" prefWidth="100.0" />
</columnConstraints>
<rowConstraints>
<RowConstraints maxHeight="135.60001220703126" minHeight="10.0" prefHeight="88.20001220703125" vgrow="SOMETIMES" />
<RowConstraints maxHeight="201.9999984741211" minHeight="10.0" prefHeight="100.79998016357423" vgrow="SOMETIMES" />
<RowConstraints maxHeight="201.9999984741211" minHeight="10.0" prefHeight="112.80001983642575" vgrow="SOMETIMES" />
</rowConstraints>
<children>
<Text fill="#b0c926" strokeType="OUTSIDE" strokeWidth="0.0" text="Choix d'un contact" GridPane.columnSpan="2">
<font>
<Font name="OCR A Extended" size="26.0" />
</font>
</Text>
<ComboBox fx:id="choixContact" onAction="#demarrerSessionAvec" prefHeight="26.0" prefWidth="355.0" GridPane.columnSpan="2" GridPane.rowIndex="1" />
</children>
</GridPane>
</children>
</HBox>
<HBox alignment="BOTTOM_RIGHT" prefHeight="63.0" prefWidth="600.0" style="-fx-background-color: #3299a8;">
<children>
<Button fx:id="MenuButton" alignment="CENTER" mnemonicParsing="false" onAction="#retourMenu" style="-fx-background-color: #b0c926;" text="Retour au menu" textFill="WHITE">
<font>
<Font name="OCR A Extended" size="18.0" />
</font>
</Button>
</children>
</HBox>
</children>
</VBox>
</children>
</AnchorPane>

View file

@ -0,0 +1,54 @@
<?xml version="1.0" encoding="UTF-8"?>
<?import javafx.scene.control.Menu?>
<?import javafx.scene.control.MenuBar?>
<?import javafx.scene.control.MenuItem?>
<?import javafx.scene.layout.AnchorPane?>
<?import javafx.scene.layout.ColumnConstraints?>
<?import javafx.scene.layout.GridPane?>
<?import javafx.scene.layout.RowConstraints?>
<?import javafx.scene.layout.VBox?>
<?import javafx.scene.text.Font?>
<?import javafx.scene.text.Text?>
<VBox prefHeight="400.0" prefWidth="640.0" style="-fx-background-color: #3299a8;" xmlns="http://javafx.com/javafx/11.0.1" xmlns:fx="http://javafx.com/fxml/1" fx:controller="chatapp.View.View_Menu">
<children>
<MenuBar prefWidth="640.0" VBox.vgrow="NEVER">
<menus>
<Menu mnemonicParsing="false" text="Options">
<items>
<MenuItem fx:id="utilsActifsButton" onAction="#afficherUtilsActifs" mnemonicParsing="false" text="Utilisateurs actifs" />
<MenuItem fx:id="demarrerSessionButton" onAction="#demarrerSession" mnemonicParsing="false" text="Démarrer session" />
<MenuItem fx:id="changerPseudoButton" onAction="#changerPseudo" mnemonicParsing="false" text="Changer de pseudo" />
<MenuItem onAction="#deconnexion" mnemonicParsing="false" text="Déconnexion" />
</items>
</Menu>
</menus>
</MenuBar>
<AnchorPane maxHeight="-1.0" maxWidth="-1.0" prefHeight="-1.0" prefWidth="-1.0" VBox.vgrow="ALWAYS">
<children>
<GridPane layoutX="154.0" layoutY="119.0" prefHeight="82.0" prefWidth="392.0">
<columnConstraints>
<ColumnConstraints hgrow="SOMETIMES" minWidth="10.0" prefWidth="100.0" />
<ColumnConstraints hgrow="SOMETIMES" minWidth="10.0" prefWidth="100.0" />
</columnConstraints>
<rowConstraints>
<RowConstraints minHeight="10.0" prefHeight="30.0" vgrow="SOMETIMES" />
</rowConstraints>
<children>
<Text fill="#b0c926" strokeType="OUTSIDE" strokeWidth="0.0" text="Bienvenue">
<font>
<Font name="OCR A Extended" size="30.0" />
</font>
</Text>
<Text fx:id="pseudonyme" fill="WHITE" strokeType="OUTSIDE" strokeWidth="0.0" text="Pseudo" GridPane.columnIndex="1">
<font>
<Font name="OCR A Extended" size="30.0" />
</font>
</Text>
</children>
</GridPane>
</children>
</AnchorPane>
</children>
</VBox>

View file

@ -0,0 +1,53 @@
<?xml version="1.0" encoding="UTF-8"?>
<?import javafx.scene.control.Button?>
<?import javafx.scene.control.ScrollPane?>
<?import javafx.scene.control.TextArea?>
<?import javafx.scene.layout.AnchorPane?>
<?import javafx.scene.layout.HBox?>
<?import javafx.scene.layout.VBox?>
<?import javafx.scene.text.Font?>
<?import javafx.scene.text.Text?>
<AnchorPane maxHeight="-Infinity" maxWidth="-Infinity" minHeight="-Infinity" minWidth="-Infinity" prefHeight="400.0" prefWidth="600.0" xmlns="http://javafx.com/javafx/11.0.1" xmlns:fx="http://javafx.com/fxml/1" fx:controller="chatapp.View.View_Utilisateurs">
<children>
<VBox prefHeight="400.0" prefWidth="600.0">
<children>
<HBox alignment="CENTER" prefHeight="100.0" prefWidth="200.0" style="-fx-background-color: #3299a8;">
<children>
<Text fill="#b0c926" strokeType="OUTSIDE" strokeWidth="0.0" text="Qui est là?">
<font>
<Font name="OCR A Extended" size="48.0" />
</font>
</Text>
</children>
</HBox>
<HBox alignment="CENTER" prefHeight="304.0" prefWidth="600.0" style="-fx-background-color: #3299a8;">
<children>
<ScrollPane prefHeight="282.0" prefWidth="202.0">
<content>
<AnchorPane minHeight="0.0" minWidth="0.0" prefHeight="267.0" prefWidth="200.0">
<children>
<TextArea fx:id="ListeUtilisateurs" layoutY="12.0" prefHeight="267.2" prefWidth="200.0" style="-fx-background-color: #3299a8;" text="Aucun utilisateur actif" AnchorPane.bottomAnchor="0.0" AnchorPane.leftAnchor="0.0" AnchorPane.rightAnchor="0.0" AnchorPane.topAnchor="0.0">
<font>
<Font name="OCR A Extended" size="13.0" />
</font>
</TextArea>
</children>
</AnchorPane>
</content>
</ScrollPane>
</children>
</HBox>
<HBox alignment="BOTTOM_RIGHT" layoutX="10.0" layoutY="10.0" prefHeight="63.0" prefWidth="600.0" style="-fx-background-color: #3299a8;">
<children>
<Button fx:id="MenuButton" alignment="CENTER" mnemonicParsing="false" style="-fx-background-color: #b0c926;" onAction="#retourMenu" text="Retour au menu" textFill="WHITE">
<font>
<Font name="OCR A Extended" size="18.0" />
</font>
</Button>
</children></HBox>
</children>
</VBox>
</children>
</AnchorPane>

View file

@ -1,240 +0,0 @@
package src.Controller;
import java.io.IOException;
import java.net.DatagramSocket;
import java.net.InetAddress;
import java.net.InterfaceAddress;
import java.net.NetworkInterface;
import java.net.SocketException;
import java.net.UnknownHostException;
import java.util.ArrayList;
import java.util.Enumeration;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import src.Protocoles.*;
/**
* <p>
* Classe recapitulant toutes les actions possibles pour un utilisateur
* </p>
*/
public class ChatApp {
/* Liste des utilisateurs actifs */
private ListUtilisateurs actifUsers ;
/* Map on l'on stocke localement les historiques des messages */
private Map<String,Historique> mapHistorique ;
private boolean historiqueAvailable = true;
/* ChatApp est associe a un utilisateur */
private Utilisateur me;
/**
* Constructeur de l'application de chat
*
* @param pseudo Pseudo de l'utilisateur
* @param port Port de communication
*/
public ChatApp(String pseudo, Integer port){
this.actifUsers = new ListUtilisateurs() ;
// Recuperer adresse IP de l'utilisateur
InetAddress ip = null ;
ip = UDPEchange.getCurrentIp();
this.me = new Utilisateur(pseudo,port,ip);
this.actifUsers.addList(getMe());
this.mapHistorique = new HashMap<String,Historique>() ;
}
/**
* Mettre a jour dans Maphistorique, l'historique avec un utilisateur dont le nom est pseudo
*
* @param pseudo Pseudo de l'utilisateur
* @param h nouvel Historique entre les deux utilisateurs
*/
public synchronized void majHistorique(Historique h) {
getMapHistorique().put(h.getUser2().getPseudo(),h);
}
/*public void majHistorique2(MessageHorodate mh, String pseudo) {
Historique h = getMapHistorique().get(pseudo);
//h.addMessage(mh);
getMapHistorique().put(h.getUser2().getPseudo(),h);
}*/
public void majHistorique2(String mh, String pseudo) {
Historique h = getMapHistorique().get(pseudo);
MessageHorodate msghor = new MessageHorodate(this.getMe(),this.getMe(),"rien",1);
System.out.println(">>"+mh+"<<");
System.out.print(msghor.getDateHorodatage());
System.out.println(msghor.getDestinataire());
System.out.println(msghor.getSource());
System.out.println(msghor.getType());
h.addMessage(msghor);
getMapHistorique().put(h.getUser2().getPseudo(),h);
}
/**
* Modification du pseudo de l'utilisateur
* Envoie en broadcast ses informations utilisateurs et son nouveau pseudo
*
* @param nouveau correspond au nouveau pseudo
* @return False si modiferPseudo a echoue, True sinon
*/
public Boolean modifierPseudo(String nouveau) throws IOException {
// Message que l'on envoie à tous les utilisateurs actifs
String broadcastMessage = "Demande Modification Pseudo\n" + this.getMe().toString() + "\n" + nouveau + "\n";
UDPEchange.EnvoiBroadcast(broadcastMessage);
try {
Thread.sleep(2000);
/* L'utilisateur doit attendre la reponse de tous les utilisateurs connectes
* pour savoir si son pseudo est accepte
*/
} catch (InterruptedException e) {
e.printStackTrace();
}
if (UDPEchange.getPseudoValide()) {
System.out.println("Modification pseudo reussie");
//Envoi un msg en broadcast a tout les utilisateurs pour les prevenir de son nouveau pseudo//
broadcastMessage = "Modification pseudo reussie\n" + this.getMe().toString() + "\n" + nouveau + "\n";
UDPEchange.EnvoiBroadcast(broadcastMessage);
//-------Change son propre nom d'utilisateur-------//
this.getActifUsers().modifierList(this.getMe().getPseudo(), nouveau);
this.getMe().setPseudo(nouveau);
System.out.println("Changement pseudo accepte, nouvelle liste des utilisateurs actifs:");
this.getActifUsers().afficherListeUtilisateurs();
return true;
}
else
{
System.out.println("Echec Modification pseudo");
return false;
}
}
/**
* Methode appelee lors de la connexion d'un nouvel utilisateur.
* Il va prevenir les utilisateurs du reseau de son arrivee.
* @return False si Connexion a echoue, True sinon
*/
public Boolean connexion() throws IOException {
// Message que l'on envoie à tous les utilisateurs actifs
String broadcastMessage = "Connexion\n" + this.getMe().toString() ;
UDPEchange.EnvoiBroadcast(broadcastMessage);
try {
Thread.sleep(2000); // L'utilisateur doit attendre la reponse de tous les utilisateurs connectes
} catch (InterruptedException e) {
e.printStackTrace();
}
if (UDPEchange.getConnecte()) {
System.out.println("Connexion reussie");
return true;
}
else
{
System.out.println("Connexion echoue");
UDPEchange.setConnecte(true);
return false ;
}
}
/**
* Methode appelee lors de la deconnexion de l'utilisateur.
* Il va prevenir les utilisateurs du reseau de son depart.
*
*/
public void deconnexion() throws IOException {
// Message que l'on envoie à tous les utilisateurs actifs
String broadcastMessage = "Deconnexion\n" + this.getMe().toString() ;
UDPEchange.EnvoiBroadcast(broadcastMessage);
System.exit(1);
}
/**
* Getter
* @return Utilisateur associee a ChatApp
*/
public Utilisateur getMe() {
return me;
}
/**
* Getter
* @return Liste des utilisateurs actifs associee a ChatApp
*/
public ListUtilisateurs getActifUsers() {
return actifUsers;
}
/**
* Getter
* @return la map des historiques
*/
public Map<String,Historique> getMapHistorique() {
return mapHistorique;
}
/**
* Obtenir l'historique entre deux utilisateurs
* @param pseudo Pseudo de l'utilisateur dont on souhaite obtenir l'historique
* @return Un historique
*/
public synchronized Historique getHist(String pseudo) {
Historique h = this.mapHistorique.get(pseudo);
if( h != null) {
return h ;
}
else {
h = new Historique(this.me, this.getActifUsers().getPseudoList(pseudo));
return h ;
}
}
public static void main (String[] args) throws IOException {
ChatApp app = new ChatApp(args[0],Integer.parseInt(args[1])) ;
ExecutorService execUDP = Executors.newFixedThreadPool(1000);
execUDP.submit(new RunnerEcouteUDP(app));
try {
app.connexion();
} catch (IOException e) {
e.printStackTrace();
}
ExecutorService execTCP = Executors.newFixedThreadPool(1000);
execTCP.submit(new RunnerEcouteTCP(app));
try {
Thread.sleep(5000);
} catch (InterruptedException e) {
e.printStackTrace();
}
if(app.getMe().getPseudo().equals("Marvel")) {
app.getHist("Doudou").afficher10derniers();
System.out.println("Tentative de connexion avec Doudou");
TCPEchange.demarrerSession(app, app.actifUsers.getPseudoList("Doudou"));
}
}
public boolean isHistoriqueAvailable() {
return historiqueAvailable;
}
public void setHistoriqueAvailable(boolean historiqueAvailable) {
this.historiqueAvailable = historiqueAvailable;
}
}

View file

@ -1,63 +0,0 @@
package src.Controller;
import java.util.ArrayList;
/**
* <p>
* Classe permettant de sauvegarder les échanges entre deux utilisateurs
* </p>
*/
public class Historique {
private Utilisateur User1;
private Utilisateur User2;
// Liste conservant les differents échanges
private ArrayList<MessageHorodate> HistoriqueHorodate ;
/**
* <p>
* Constructeur : un historique sauvegarde les echanges entre
* User1 et User2
* @param User1 - un utilisateur
* @param User2 - un second utilisateur
* </p>
*/
public Historique(Utilisateur User1, Utilisateur User2) {
this.User1 = User1;
this.User2 = User2;
this.HistoriqueHorodate = new ArrayList<MessageHorodate>();
}
/**
* <p>
* On ajoute un message échangé dans la liste 'HistoriqueHorodate'
*
* @param mh - le message horodate échangé
* </p>
*/
public void addMessage(MessageHorodate mh) {
this.HistoriqueHorodate.add(mh);
}
/**
* <p>
* getter pour recuperer le second utilisateur
* </p>
*/
public Utilisateur getUser2() {
return User2;
}
public void afficher10derniers() {
System.out.println("Demarrage de l'affichage partiel de l'historique");
System.out.println("Il y a actuellement " + HistoriqueHorodate.size() +" elements dans l'historique");
int n =10;
if(HistoriqueHorodate.size()<=10) {
n = HistoriqueHorodate.size();
}
for(int i = 0; i<n;i++) {
String exp = HistoriqueHorodate.get(i).getSource().getPseudo();
String payload = HistoriqueHorodate.get(i).getMessage();
System.out.println(exp+" : "+payload);
}
}
}

View file

@ -1,114 +0,0 @@
package src.Controller;
import java.util.ArrayList;
public class ListUtilisateurs {
private ArrayList<Utilisateur> actifUsers ;
public ListUtilisateurs() {
this.actifUsers = new ArrayList<Utilisateur>() ;
}
/**
* Ajouter des utilisateurs actifs dans l'attribut liste 'actifUsers'
*
* @param u on va rajouter cet utilisateur dans la liste
*/
public void addList(Utilisateur u) {
if((verifierUnicite(u.getPseudo()))) {
this.actifUsers.add(u);
}
}
/**
* Recuperer un utilisateur à partir de son pseudo
*
* @param pseudo Pseudo de l'utilisateur que l'on souhaite retrouver
*/
public Utilisateur getPseudoList(String pseudo) {
for(Utilisateur elem: this.actifUsers)
{
if (elem.getPseudo().equals(pseudo) ) {
return elem ;
}
}
return null ;
}
/**
* Supprimer de la liste des utilisateurs actifs 'actifUsers' un certain utilisateur
*
* @param u on va supprimer cet utilisateur dans la liste
*/
public void supprimerList(Utilisateur u) {
Boolean Sup = false ;
for(Utilisateur elem: this.actifUsers)
{
if (elem.equals(u) ) {
this.actifUsers.remove(elem);
Sup = true ;
this.afficherListeUtilisateurs();
}
}
if (!Sup) {
System.out.println("Tentative de retirer un objet non contenu dans la liste");
}
}
/**
* Modifie le nom d'un utilisateur dans la liste des utilisateurs actifs 'actifUsers'
*
* @param ancien correspond au pseudo remplacer
* @param nouveau correspond au nouveau pseudo
*/
public void modifierList(String ancien , String nouveau) {
for(Utilisateur elem: this.actifUsers)
{
if (ancien.equals( elem.getPseudo() ) ) {
this.actifUsers.remove(elem);
elem.setPseudo(nouveau);;
this.addList(elem);
}
}
this.afficherListeUtilisateurs();
}
public Boolean appartient(Utilisateur u) {
return this.actifUsers.contains(u);
}
/**
* Verifie qu'aucun autre utilisateur ne possède le même pseudo
*
* @param u on va supprimer cet utilisateur dans la liste
*/
public Boolean verifierUnicite(String pseudo) {
for(Utilisateur elem: this.actifUsers)
{
if (pseudo.equals( elem.getPseudo() ) ) {
return false ;
}
}
return true;
}
/**
* Méthode affichant la liste des utilisateurs actifs
*
*/
public String afficherListeUtilisateurs() {
System.out.println ("Liste des utilisateurs actifs : ");
String Utilisateur = "" ;
for(Utilisateur elem: this.actifUsers)
{
System.out.println (elem.toString());
Utilisateur += (elem + "\n");
}
return Utilisateur;
}
}

View file

@ -1,142 +0,0 @@
package src.Controller;
import java.text.DateFormat;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;
/**
* <p>
* Classe representant les messages envoyés en TCP lors d'une session de clavardage
* </p>
*/
public class MessageHorodate {
private Utilisateur destinataire ;
private Utilisateur source ;
private Date dateHorodatage ;
private int type; // 0 = debut de la communication, 1= message de communication, 2 = fin de la communicataion
private String Message;
/**
* <p>
* Constructeur , le message va etre horodate
* @param destinataire - Destinataire du message
* @param source - Source du message
* @param Message - Message envoye
* </p>
*/
public MessageHorodate(Utilisateur destinataire, Utilisateur source, String Message, int type) {
this.setDestinataire(destinataire) ;
this.setSource(source) ;
this.setMessage(Message) ;
this.setDateHorodatage(new Date());
this.type = type;
}
public void setDate(Date d) {
this.setDateHorodatage(d);
}
/**
* <p>
* permet de creer une representation string du message
* @return Les differents attributs de la classe sous forme de string
* </p>
*/
@Override
public String toString() {
String Msg = "";
Msg += ("Destinataire::" + this.getDestinataire() + "\n") ;
Msg += ("Source::" + this.getSource()+ "\n") ;
Msg += ("Type::"+ this.type+ "\n");
Msg += ("Date::" + this.dateToString() + "\n") ;
Msg += ("Message::" + this.getMessage() + "\n" );
return Msg ;
}
/**
* <p>
* permet de creer une representation string de la date d'horodatage
* @return La date d'horodatage du message en format yyyy/MM/dd HH:mm:ss
* </p>
*/
public String dateToString() {
DateFormat format = new SimpleDateFormat("yyyy/MM/dd HH:mm:ss");
return format.format(this.getDateHorodatage());
}
/**
* <p>
* Permet de re creer un message horodate a partir d'un string
* @return un messageHorodate
* </p>
*/
public static MessageHorodate stringToMessageHorodate(String s) {
String mots[] = s.split("\n");
Utilisateur destinataire = Utilisateur.stringToUtilisateur(mots[0].split("::")[1]);
Utilisateur source = Utilisateur.stringToUtilisateur(mots[1].split("::")[1]);
int type = Integer.parseInt(mots[2].split("::")[1]);
DateFormat format = new SimpleDateFormat("yyyy/MM/dd HH:mm:ss");
Date date = new Date();
/*try {
date = format.parse(mots[3].split("::")[1]);
} catch (Exception e) {
e.printStackTrace();
}*/
String payload = "";
for(int i=4; i< mots.length; i++) {
if(mots[i].startsWith("Message::")) {
mots[i]=mots[i].split("::")[1];
}
payload += mots[i]+"\n";
}
MessageHorodate mh = new MessageHorodate(destinataire, source, payload, type);
//mh.setDate(date);
return mh ;
}
public Utilisateur getSource() {
return source;
}
public void setSource(Utilisateur source) {
this.source = source;
}
public Utilisateur getDestinataire() {
return destinataire;
}
public void setDestinataire(Utilisateur destinataire) {
this.destinataire = destinataire;
}
public String getMessage() {
return Message;
}
public void setMessage(String message) {
Message = message;
}
public int getType() {
return type;
}
public void setType(int Type) {
this.type = type;
}
public Date getDateHorodatage() {
return dateHorodatage;
}
public void setDateHorodatage(Date dateHorodatage) {
this.dateHorodatage = dateHorodatage;
}
}

View file

@ -1,51 +0,0 @@
package src.Controller;
import java.awt.BorderLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.io.IOException;
import javax.swing.ImageIcon;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.JTextField;
import javax.swing.SwingConstants;
public class Modification_Pseudo extends JPanel{
ChatApp app;
public Modification_Pseudo(String name, ChatApp app) {
this.app = app ;
JLabel Text = new JLabel("Entrez un nouveau nom d'utilisateur!", SwingConstants.CENTER);
JTextField pseudofield = new JTextField(2); // Zone d'insertion de texte
JButton home = new JButton(new ImageIcon("/Users/auriane/Desktop/ChatApp-AL-NM/Implementation/src/images/Home.png"));
//Ajout d'un bouton Valider
JButton Valider = new JButton("Valider");
this.getRootPane().setDefaultButton(Valider);
//Listen to events from the Valider button.
Valider.addActionListener(new ActionListener(){
public void actionPerformed(ActionEvent event) {
String nouveau = pseudofield.getText();
try {
Boolean resultat = app.modifierPseudo(nouveau);
if(resultat) {
}
else {
//JOptionPane.showMessageDialog(this, "Echec de modification de pseudo, " + nouveau +" deja pris", JOptionPane.WARNING_MESSAGE);
}
} catch (IOException e) {
e.printStackTrace();
}
}
});
this.add(home);
this.add(Text);
this.add(BorderLayout.CENTER,pseudofield);
this.add(BorderLayout.SOUTH,Valider);
}
}

View file

@ -1,77 +0,0 @@
package src.Controller;
import java.net.InetAddress;
import java.net.UnknownHostException;
public class Utilisateur extends Object {
private String pseudo ;
private Integer port;
private InetAddress ip ;
private String id ;
public Utilisateur(String pseudo,Integer port, InetAddress ip ){
this.setPseudo(pseudo) ;
this.setPort(port);
this.ip = ip ;
this.id = ip.getHostName() ;
}
public String getPseudo() {
return pseudo;
}
public void setPseudo(String pseudo) {
this.pseudo = pseudo;
}
public Integer getPort() {
return port;
}
public void setPort(Integer port) {
this.port = port;
}
public InetAddress getIp() {
return ip;
}
public String getId() {
return id;
}
@Override
public String toString(){
String s = "";
s+="pseudo " + this.pseudo + " | ";
s+="port " + (this.port).toString() + " | ";
s+="ip " + (this.ip).toString() + " | ";
s+="id " + (this.id).toString() + " | ";
return s;
}
public static Utilisateur stringToUtilisateur(String s) {
String name = "";
Integer port = 0;
String ip = "" ;
String id = "";
String mots[] = s.split(" ");
name=mots[1];
port=Integer.parseInt(mots[4]);
ip=mots[7];
id=mots[10];
Utilisateur user = null;
try {
user = new Utilisateur(name,port,InetAddress.getByName(ip.split("/")[1]));
} catch (UnknownHostException e) {
e.printStackTrace();
}
return user;
}
public Boolean equals(Utilisateur u) {
return this.getId().equals( u.getId() ) ;
}
}

View file

@ -1,16 +0,0 @@
package src.Protocoles;
import src.Controller.ChatApp;
public class RunnerEcouteTCP implements Runnable {
ChatApp app ;
public RunnerEcouteTCP(ChatApp app) {
this.app = app ;
}
@Override
public void run() {
TCPEchange.ecouteTCP(app);
}
}

View file

@ -1,16 +0,0 @@
package src.Protocoles;
import src.Controller.ChatApp;
public class RunnerEcouteUDP implements Runnable {
ChatApp app ;
public RunnerEcouteUDP(ChatApp app) {
this.app = app ;
}
@Override
public void run() {
UDPEchange.ecouteUDP(app);
}
}

View file

@ -1,320 +0,0 @@
package src.Protocoles;
import java.io.InputStream;
import java.io.PrintStream;
import java.io.PrintWriter;
import java.io.OutputStream;
import java.net.DatagramSocket;
import java.net.ServerSocket;
import java.net.Socket;
import java.net.SocketException;
import java.util.NoSuchElementException;
import java.util.Scanner;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import src.Controller.*;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
/**
* <p>
* Classe representant les échanges TCP entre utilisateurs.
* </p>
*/
public class TCPEchange {
/**
* <p>
* Equivalent a un handshake.
* L'utilisateur associé a app souhaite entamé une discussion avec User2
* @param app L'app associé à l'utilisateur qui souhaite entamé la discussion
* @param User2 Le destinataire
* </p>
*/
public static void demarrerSession(ChatApp app,Utilisateur User2 ) throws IOException {
System.out.println("Demmarrage d'une session de clavardage");
Socket s = new Socket(User2.getIp(),5000);
System.out.println("Socket de demarrage d'une session cree");
//ExecutorService exec = Executors.newFixedThreadPool(1000);
Thread t1 = new Thread(new RunnerTCPEcoute(s,app));
Thread t2 = new Thread(new RunnerTCPEnvoi(s,app,User2,false));
t1.start();
t2.start();
try {
t1.join();
t2.join();
}catch(InterruptedException e) {
System.out.println("Un thread s'est arrete brusquement");
}
System.out.println("Tout s'est passe creme");
app.getHist(User2.getPseudo()).afficher10derniers();
}
/*public static void envoiTCP(ChatApp app,Utilisateur User2, String Msg, int type ) {
// On cree un messagehorodate
MessageHorodate mh = new MessageHorodate(app.getMe(), User2, Msg, type);
if( type == 1 ) {
// on ajoute le msg à son historique
Historique h = app.getHist(User2.getPseudo());
h.addMessage(mh);
// on update la liste des historiques de app
app.majHistorique(h);
}
try {
Socket s = new Socket(User2.getIp(), User2.getPort());
PrintStream output = new PrintStream(s.getOutputStream());
output.println(mh.toString());
output.close();
s.close();
} catch (Exception e) {
e.printStackTrace();
}
}*/
/**
* <p>
* Méthode pour qu'un objet de la classe ChatApp soit constamment en écoute de potentielles connexions
* @param app L'utilisateur en écoute de potentielles communications
* </p>
*/
public static void ecouteTCP(ChatApp app) {
ServerSocket ss = null;
ExecutorService exec = Executors.newFixedThreadPool(1000);
System.out.println("Ecoute TCP activee");
try {
ss = new ServerSocket(5000); // On ecoute sur le port 5000
System.out.println("Socket d'ecoute cree");
while(true) { // Ecoute en boucle
System.out.println("Attente Session de clavardage");
Socket link = ss.accept(); // Blocante
exec.submit(new RunnerTCPEcoute(link,app)); // On crée un thread qui va gerer la connexion recu
System.out.println("L'ecoute TCP continue apres le premier thread demarre");
}
}
catch (Exception e) {
e.printStackTrace();
}
}
}
/**
* <p>
* Classe representant les threads s'occupant de l'envoie de messages en utilisant le protocole TCP.
* Cette classe implemente l'interface Runnable.
* </p>
*/
class RunnerTCPEnvoi implements Runnable {
private Socket link;
private ChatApp app ;
private Utilisateur Destinataire;
final BufferedReader in;
final PrintWriter out;
final Scanner sc=new Scanner(System.in);
private boolean bonjourEnvoye = false;
/**
* <p>
* Constructeur de la classe RunnerTCPEnvoi
* @param link
* @param app Un objet ChatApp dont l'utilisateur associé souhaite entame une discussion
* @param user2 Destinataire
* @param bonjour Boolean true si c'est le debut d'une connexion, false sinon
* </p>
*/
public RunnerTCPEnvoi(Socket link,ChatApp app, Utilisateur user2, boolean bonjour ) throws IOException {
this.link = link;
this.app = app;
this.Destinataire = user2;
this.out = new PrintWriter(link.getOutputStream());
this.in = new BufferedReader (new InputStreamReader (link.getInputStream()));
this.bonjourEnvoye = bonjour;
}
@Override
public void run() {
System.out.println("Creation d'un thread d'envoi");
String msg;
while(true){
if(!bonjourEnvoye) { // bonjourEnvoye est a false si c'est le debut d'une communication
MessageHorodate mh = new MessageHorodate(Destinataire,app.getMe(),"Bonjour",2);
bonjourEnvoye = true;
System.out.println("Envoi d'un bonjour");
out.println(mh);
out.flush();
}
else {
try {
msg = sc.nextLine();
}catch(NoSuchElementException e) {
break;
}
MessageHorodate mh = new MessageHorodate(Destinataire,app.getMe(),msg,1);
if(msg.equals("--STOP--")) {
mh = new MessageHorodate(Destinataire,app.getMe(),msg,0); // ENVOYER JUSTE --STOP-- SUFFIT
out.println(mh);
out.flush();
break;
}
/* while(!app.isHistoriqueAvailable()) {
try{wait();
}catch(InterruptedException e) {}
}*/
//app.setHistoriqueAvailable(false);
synchronized( this.app.getMapHistorique()) {
Historique h = app.getHist(Destinataire.getPseudo());
h.addMessage(mh);
app.majHistorique(h);
}
// on update la liste des historiques de app
//app.majHistorique2(mh.toString(),Destinataire.getPseudo());
//app.setHistoriqueAvailable(false);
//notifyAll();
out.println(mh);
System.out.println("Envoi d'un mesage");
out.flush();
}
}
try {
System.out.println("Fermeture du thread d'envoi");
in.close();
link.close();
}catch(Exception e) {
// Gestion de l'exception de la fermeture de la socket
}
}
}
/**
* <p>
* Classe representant les threads s'occupant de la reception de messages en utilisant le protocole TCP.
* Cette classe implemente l'interface Runnable.
* </p>
*/
class RunnerTCPEcoute implements Runnable {
final Socket link;
private ChatApp app ;
private Utilisateur u2;
private boolean u2Initialise;
public RunnerTCPEcoute(Socket link,ChatApp app ) {
this.link = link;
this.app = app;
this.u2Initialise=false;
}
@Override
public void run() {
System.out.println("Creation d'un thread d'ecoute");
try {
PrintStream output = new PrintStream(link.getOutputStream());
//InputStream is = link.getInputStream();
BufferedReader in = new BufferedReader (new InputStreamReader (link.getInputStream()));
String line = "";
String dest = "";
String src = "";
String type = "";
String date = "";
String payload = "";
String msg = "";
line = in.readLine();
while (line != null) {
if(line.split("::")[0].equals("Destinataire")) {
if(msg.equals("")) {
dest = line+"\n";
msg=".";
}
else {
msg=dest+src+type+date+payload;
payload = "";
MessageHorodate mh = MessageHorodate.stringToMessageHorodate(msg);
System.out.println("Type du message:"+mh.getType());
if(mh.getType()==1) {
/*while(!app.isHistoriqueAvailable()) {
try{wait();
}catch(InterruptedException e) {}
}
app.setHistoriqueAvailable(false);*/
System.out.println("Historique mis à jour lors de la reception");
Historique h = app.getHist(mh.getSource().getPseudo());
h.addMessage(mh);
app.majHistorique(h);
//app.setHistoriqueAvailable(true);
//notifyAll();
//app.majHistorique2(mh,mh.getSource().getPseudo());
}
else if(mh.getType()==0) {
break;
}
}
}
else if(line.split("::")[0].equals("Source")) {
src = line+"\n";
if(!u2Initialise) {
u2=Utilisateur.stringToUtilisateur(src.split("::")[1].replaceAll("\n", ""));
System.out.println("u2Initialise !");
u2Initialise = true;
}
}
else if(line.split("::")[0].equals("Type")) {
if(line.split("::")[1].equals("2")) {
System.out.println("Bonjour recu!");
//System.out.println(src.split("::")[1].replaceAll("\n", ""));
u2=Utilisateur.stringToUtilisateur(src.split("::")[1].replaceAll("\n", ""));
u2Initialise = true;
System.out.println("Pseudo du poto: >>"+u2.getPseudo()+"<<");
Thread t = new Thread(new RunnerTCPEnvoi(link,app,u2,true));
t.start();
System.out.println("Thread d'envoi envoye");
}
type = line+"\n";
}
else if(line.split("::")[0].equals("Date")) {
date = line+"\n";
}
else if(line.split("::")[0].equals("Message")){
payload = line+"\n";
}
else {
payload += line+"\n";
}
System.out.println("Received: "+ line);
line = in.readLine();
}
System.out.println("Affichage de l'histo");
System.out.println("Pseudo du poto: >>"+u2.getPseudo()+"<<");
app.getHist(u2.getPseudo()).afficher10derniers();
in.close();
link.close();
} catch (IOException e) {
//e.printStackTrace();
} finally {
System.out.println("Finishing thread");
System.out.println("Affichage de l'histo");
System.out.println("Pseudo du poto: >>"+u2.getPseudo()+"<<");
app.getHist(u2.getPseudo()).afficher10derniers();
}
}
}

View file

@ -1,358 +0,0 @@
package src.Protocoles;
import java.io.IOException;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.InetAddress;
import java.net.NetworkInterface;
import java.net.SocketException;
import java.net.Inet4Address;
import java.util.ArrayList;
import java.util.Enumeration;
import java.util.List;
import java.util.Objects;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import src.Controller.*;
/**
* <p>
* Classe representant les echanges UDP entre utilisateurs.
* </p>
*/
public class UDPEchange {
private static Boolean Connecte = true;
// True si l'utilisateur peut se connecter avec ce nom d'utilisateur , False sinon
/**
* Getter
* @return le boolean connecte (True s'il peut se connecter avec ce nom d'utilisateur , False sinon)
*/
public static Boolean getConnecte() {
return Connecte;
}
/**
* Setter
* @param value La nouvelle valeur du boolean de connexion
*/
public static void setConnecte(Boolean value) {
Connecte = value ;
}
private static Boolean PseudoValide = true;
// True si l'utilisateur a (ou demande) un pseudo valide , False sinon
/**
* Getter
* @return le boolean PseudoValide (True s'il peut utiliser ce pseudo , False sinon)
*/
public static Boolean getPseudoValide() {
return PseudoValide;
}
/**
* Setter
* @param value La nouvelle valeur du boolean concernant le pseudo valide
*/
public static void setPseudoValide(Boolean value) {
PseudoValide = value ;
}
public static InetAddress getCurrentIp() {
try {
Enumeration<NetworkInterface> networkInterfaces = NetworkInterface
.getNetworkInterfaces();
while (networkInterfaces.hasMoreElements()) {
NetworkInterface ni = (NetworkInterface) networkInterfaces
.nextElement();
Enumeration<InetAddress> nias = ni.getInetAddresses();
while(nias.hasMoreElements()) {
InetAddress ia= (InetAddress) nias.nextElement();
if (!ia.isLinkLocalAddress()
&& !ia.isLoopbackAddress()
&& ia instanceof Inet4Address) {
return ia;
}
}
}
} catch (Exception e) {
System.out.println("unable to get current IP " + e.getMessage());
}
return null;
}
/**
* <p>
* Méthode permettant d'envoyer un message à tout les utilisateurs
* a l'aide du protocole UDP
* </p>
* @param broadcastMessage correspond au message a transmettre aux utilisateurs
*/
public static void EnvoiBroadcast(String broadcastMessage) throws IOException {
int port = 1234 ;
// Envoie en broadcast à tous les utilsateurs
for (InetAddress broadcastAddr : listAllBroadcastAddresses()) {
DatagramSocket socket = new DatagramSocket();
socket.setBroadcast(true);
byte[]buffer = broadcastMessage.getBytes();
DatagramPacket packet = new DatagramPacket( buffer, buffer.length, broadcastAddr,port);
socket.send(packet);
socket.close();
System.out.println("Broadcast sent with address " + broadcastAddr.toString());
System.out.println("***********Message envoye***********");
System.out.println("Dest Ip: " + broadcastAddr.toString());
System.out.println("Dest port: " + String.valueOf(port));
System.out.println("Contenu: ");
System.out.println(broadcastMessage);
System.out.println("************************************");
}
}
/**
* <p>
* Methode permettant la reception de messages d'utilisateurs
* a l'aide du protocole UDP
* </p>
* @param app L'application de chat de l'utilisateur qui receptionne le message
*/
public static void ecouteUDP(ChatApp app)
{
DatagramSocket socket = null;
ExecutorService exec = Executors.newFixedThreadPool(1000);
try {
socket = new DatagramSocket(1234);
} catch (SocketException e1) {
e1.printStackTrace();
}
byte buffer[] = new byte[1024];
System.out.println("Ecoute sur le port: 1234");
while(true)
{
DatagramPacket data = new DatagramPacket(buffer,buffer.length);
try {
socket.receive(data);
} catch (IOException e) {
e.printStackTrace();
}
// Un thread est lance à chaque reception d'un message
System.out.println("Message recu!");
exec.submit(new RunnerUDP(data,app));
}
}
/**
* <p>
* Methode permettant d'envoyer un message a utilisateur en particulier
* a l'aide du protocole UDP
* </p>
* @param Adress l'addresse de l'utilisateur
* @param Message correspond au message à transmettre a l'utilisateur
*/
public static void envoiUnicast( InetAddress Adress , String Message ) throws IOException {
DatagramSocket socket = new DatagramSocket();
byte[]buffer = Message.getBytes();
DatagramPacket packet = new DatagramPacket( buffer, buffer.length, Adress, 1234 );
socket.send(packet);
socket.close();
System.out.println("***********Message envoye***********");
System.out.println("Dest Ip: " + Adress.toString());
System.out.println("Dest port: " + String.valueOf(1234));
System.out.println("Contenu: ");
System.out.println(Message);
System.out.println("************************************");
}
/**
* <p>
* Methode permettant de recuperer la liste des adresses de broadcast, chacune associer à une interface de la machine
* </p>
*/
static List<InetAddress> listAllBroadcastAddresses() throws SocketException {
List<InetAddress> broadcastList = new ArrayList<>();
Enumeration<NetworkInterface> interfaces
= NetworkInterface.getNetworkInterfaces();
while (interfaces.hasMoreElements()) {
NetworkInterface networkInterface = interfaces.nextElement();
if (networkInterface.isLoopback() || !networkInterface.isUp()) {
continue;
}
networkInterface.getInterfaceAddresses().stream()
.map(a -> a.getBroadcast())
.filter(Objects::nonNull)
.forEach(broadcastList::add);
}
return broadcastList;
}
}
/**
* <p>
* Classe implementant l'interface Runnable.
* Contient les traitements a executer dans un thread lancer par des methodes de la class UDPEchange
* </p>
*/
class RunnerUDP implements Runnable {
final DatagramPacket data ;
ChatApp app ;
public RunnerUDP(DatagramPacket data, ChatApp app) {
this.data= data;
this.app = app ;
}
/**
* <p>
* Methode qui redefinie les traitements qui seront executes dans le thread:
* Met à jour la liste des utilisateurs actifs
* </p>
*
*/
@Override
public void run() {
System.out.println("Thread started");
String received = new String(data.getData(), 0, data.getLength());
System.out.println("***********Message recu***********");
System.out.println(received);
System.out.println("**********************************");
String Type = received.split("\n")[0];
//****************************************************************************************************
//****************************************************************************************************
//****************************************Demande de connexion****************************************
//****************************************************************************************************
//****************************************
if (Type.equals("Connexion")) { // un utilisateur vient d'arriver sur le reseau
System.out.println("Reception d'une demande de connexion");
Utilisateur u = Utilisateur.stringToUtilisateur(received.split("\n")[1]);
if (! u.equals(this.app.getMe())) { // On envoit en broadcast mais on ne souhaite pas recevoir de message de nous même
String reponse = "Reponse Connexion\n";
if (!( app.getActifUsers() ).verifierUnicite(u.getPseudo())) {
System.out.println("Pseudo deja present dans la liste");
reponse += "false\n";
}
else {
System.out.println("Ajout d'un nouvel utilisateur dans la liste des Utilisateurs");
( app.getActifUsers() ).addList(u);
reponse += "true\n";
}
reponse += app.getMe().toString();
try {
UDPEchange.envoiUnicast(u.getIp(),reponse);
}catch(IOException e)
{
System.out.println("Echec de l'envoi du message");
}
( app.getActifUsers() ).afficherListeUtilisateurs();
}
}
//*******************************************************************************************************
//*******************************************************************************************************
//****************************************Reponse d'une connexion****************************************
//*******************************************************************************************************
//*******************************************************************************************************
if (Type.equals("Reponse Connexion")) { // Un utilisateur te repond suite à ta demande de connexion
if((received.split("\n")[1]).equals("true")) {
Utilisateur u = Utilisateur.stringToUtilisateur(received.split("\n")[2]);
app.getActifUsers().addList(u);
app.getActifUsers().afficherListeUtilisateurs();
}
else {
System.out.println("Pseudo deja pris");
UDPEchange.setConnecte(false);
}
}
//*******************************************************************************************************************
//*******************************************************************************************************************
//****************************************Demande de modification d'un pseudo****************************************
//*******************************************************************************************************************
//*******************************************************************************************************************
if (Type.equals("Demande Modification Pseudo")) {
Utilisateur Source = Utilisateur.stringToUtilisateur(received.split("\n")[1]);
if (! Source.equals(this.app.getMe())) { // On envoit en broadcast mais on ne souhaite pas recevoir de message de nous même
String nouveau = received.split("\n")[2] ;
String Message = "";
if(( app.getActifUsers() ).verifierUnicite(nouveau)) {
Message = "Bon Choix Pseudo\n" + nouveau ;
}
else {
Message = "Mauvais Choix Pseudo\n" ;
}
System.out.println(Message);
try {
UDPEchange.envoiUnicast(Source.getIp(),Message);
} catch (IOException e) {
e.printStackTrace();
}
}
}
//************************************************************************************************************
//************************************************************************************************************
//**************************************** Modification pseudo reussi ****************************************
//************************************************************************************************************
//************************************************************************************************************
if (Type.equals("Modification pseudo reussi")) {
Utilisateur Source = Utilisateur.stringToUtilisateur(received.split("\n")[1]);
if (! Source.equals(this.app.getMe())) { // On envoit en broadcast mais on ne souhaite pas recevoir de message de nous même
String nouveau = received.split("\n")[2] ;
if(app.getActifUsers().appartient(Source)) { // On verifie d'abord que Source appartient bien a la liste des utilisateurs actifs
app.getActifUsers().modifierList(Source.getPseudo(), nouveau);
}
{
// Suite a une perte d'un message lors d'une connexion l'utilisateur Source n'apparait pas dans la liste
app.getActifUsers().addList(Source);
}
}
}
//*********************************************************************************************************
//*********************************************************************************************************
//****************************************Mauvais choix d'un pseudo****************************************
//*********************************************************************************************************
//*********************************************************************************************************
if (Type.equals("Mauvais Choix Pseudo")) {
System.out.println("Ce choix de pseudo est déjà pris il te faut en choisir un autre");
UDPEchange.setPseudoValide(false);
}
//******************************************************************************************************************
//******************************************************************************************************************
//****************************************Bon choix d'un pseudo*****************************************************
//******************************************************************************************************************
//******************************************************************************************************************
if (Type.equals("Bon Choix Pseudo")) {
// Il n'y a rien a faire ici
}
//*********************************************************************************************************
//*********************************************************************************************************
//****************************************Demande d'une deconnexion****************************************
//*********************************************************************************************************
//*********************************************************************************************************
if (Type.equals("Deconnexion")) {
( app.getActifUsers() ).supprimerList(Utilisateur.stringToUtilisateur(received.split("\n")[1]));
}
}
}

View file

@ -1,133 +0,0 @@
package src.View;
import java.awt.BorderLayout;
import java.awt.Dimension;
import java.awt.GridLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
import java.io.IOException;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import javax.swing.BorderFactory;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.JTextField;
import javax.swing.SwingConstants;
import src.Controller.*;
import src.Protocoles.*;
/*
* Classe represenyant la fenetre d'accueil pour la connexion d'un utilisateur.
*/
public class View_Accueil implements ActionListener{
JFrame frame;
JPanel panel;
JTextField pseudofield;
JLabel Text;
JButton Connexion;
/*
* Constructeur d'une fenetre d'affichage pour la connexion d'un utilisateur.
* Cette fenetre sera munie d'un bouton de connexion et d'une zone de saisie de pseudo.
*/
public View_Accueil () {
//creer une instance JFrame
frame = new JFrame("ChatApp-AL-NM");
//sortir quand lutilisateur ferme le frame
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
// fixer les dimensions de la fenetre
frame.setSize(new Dimension(120, 40));
//Creer le JPanel
panel = new JPanel(new GridLayout(3,1));
//Ajouter les elements
this.addWidgets();
//Set the default button.
frame.getRootPane().setDefaultButton(Connexion);
//Ajouter le panel a la window
frame.getContentPane().add(panel, BorderLayout.CENTER);
//L'utilisateur ne pourra pas aggrandir la fenetre
this.frame.setResizable(false);
//Afficher la fenetre
frame.pack();
frame.setVisible(true);
}
/**
* Creer et ajouter les outils de la fenetre
*/
private void addWidgets() {
// Créer Zone d'insertion de texte pour le pseudo
this.pseudofield = new JTextField(2);
// creation d'un label qui contiendra un txt au centre
this.Text = new JLabel("Bonjour, Entrez un nom d'utilisateur!", SwingConstants.CENTER);
//Ajout d'un bouton Connexion
this.Connexion = new JButton("Connexion");
//On associe au bouton Connexion des actions a realiser
this.Connexion.addActionListener(this);
// On ajouter les differents elements au panel
panel.add(pseudofield);
panel.add(Text);
panel.add(Connexion);
//ajouter un effet de bord transparent au composant Jlabel
Text.setBorder(BorderFactory.createEmptyBorder(5,5,5,5));
}
/*
* Definir des traitements en réponse à un clic sur le bouton connexion
* @param event Un clic sur le bouton connexion
*/
public void actionPerformed(ActionEvent event) {
// on recupere le texte entree dans la zone de saisie
String pseudo = pseudofield.getText();
// On crée un objet de type ChatApp
ChatApp app = new ChatApp(pseudo, 3000) ;
// on crée un thread qui va ecouter les connexions entrantes
ExecutorService execUDP = Executors.newFixedThreadPool(1000);
execUDP.submit(new RunnerEcouteUDP(app));
Boolean connexion = false ;
try {
// on tente une connexion avec ce pseudo
connexion = app.connexion();
} catch (IOException e) {
e.printStackTrace();
}
// Dans les deux cas de figures (reussite ou echec) on affiche un pop-up pour expliquer la situation
if(connexion) {
// La connexion a reussi
JOptionPane.showMessageDialog(frame, "Bonjour " + pseudo) ;
frame.dispose();
// on lance une nouvelle fenetre de type View_Menu
View_Menu fenetreCourante= new View_Menu(app);
}
else {
// La connexion a echoue, il est possible de rentrer un nouveau pseudo
JOptionPane.showMessageDialog(frame, "Echec de Connexion , ce pseudo est deja pris !");
}
}
private static void createAndShowGUI() {
// Etre certain d'avoir une joli fenetre
JFrame.setDefaultLookAndFeelDecorated(true);
// On crée une fentre d'acceuil
View_Accueil fenetre = new View_Accueil();
}
public static void main(String[] args) {
//Schedule a job for the event-dispatching thread:
//creating and showing this application's GUI.
javax.swing.SwingUtilities.invokeLater(new Runnable() {
public void run() {
createAndShowGUI();
}
});
}
}

View file

@ -1,167 +0,0 @@
package src.View;
import java.awt.BorderLayout;
import java.awt.Dimension;
import java.awt.GridLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
import java.io.IOException;
import javax.swing.BoxLayout;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JTextArea;
import javax.swing.SwingConstants;
import src.Controller.*;
import java.awt.GridBagLayout;
import java.awt.Font;
import java.awt.Color;
import java.awt.GridBagConstraints;
import java.awt.Insets;
/*
* Classe representant la fenetre pour chaque session de clavardage.
*/
public class View_Clavardage {
JFrame frame ;
ChatApp app;
Utilisateur destination ; // Celui avec qui on va discuter
Utilisateur source; //Nous
WindowAdapter wa ;
JPanel panel ;
JTextArea textAreaAffichage ;
/*
* Constructeur d'une fenetre de session de clavardage.
* @param app Un objet de type ChatApp pour posseder toutes les informations de l'utilisateur
* @param User2 L'utilisateur avec qui l'on souhaite discuter et passer en parametre sous forme de String
*/
public View_Clavardage(ChatApp app, String User2) {
this.app = app ;
this.frame = new JFrame("ChatApp-AL-NM");
this.source = this.app.getMe();
this.destination = Utilisateur.stringToUtilisateur(User2);
this.frame.setDefaultCloseOperation(JFrame.DO_NOTHING_ON_CLOSE);
// fixer les dimensions de la fenetre
this.frame.setSize(new Dimension(394, 344));
this.frame.setResizable(false);
wa = new WindowAdapter(){
public void windowClosing(WindowEvent e){
int reponse = View_Menu.showConfirmDialog();
if (reponse==0){
frame.dispose();
}
}};
addWidgets();
frame.addWindowListener( wa ) ;
frame.setVisible(true);
}
/**
* Creer et ajouter les outils de la fenetre
*/
private void addWidgets() {
GridBagLayout gridBagLayout = new GridBagLayout();
gridBagLayout.columnWidths = new int[]{394, 0};
gridBagLayout.rowHeights = new int[]{16, 220, 74, 0};
gridBagLayout.columnWeights = new double[]{0.0, Double.MIN_VALUE};
gridBagLayout.rowWeights = new double[]{0.0, 0.0, 0.0, Double.MIN_VALUE};
this.frame.getContentPane().setLayout(gridBagLayout);
this.panel = new JPanel();
// Zone pour ecrire de nouveau message
JTextArea textAreaSaisie = new JTextArea(5,3);
textAreaSaisie.setLineWrap(true);
textAreaSaisie.setForeground(Color.LIGHT_GRAY);
textAreaSaisie.setFont(new Font("Lucida Grande", Font.ITALIC, 11));
textAreaSaisie.setText("Entrer du texte ici !!!");
JScrollPane scrollPane = new JScrollPane(textAreaSaisie);
// Creation d'un bouton envoye
JButton send = new JButton("Envoye");
frame.getRootPane().setDefaultButton(send);
send.addActionListener(new ActionListener(){
public void actionPerformed(ActionEvent event) {
//UTILISER TCPENVOI
String AEnvoyer = textAreaSaisie.getText();
textAreaAffichage.append(AEnvoyer);
textAreaSaisie.setText("");
}});
// Creation d'un bouton vider la zone de saisie de texte
JButton reset = new JButton("Vider");
reset.addActionListener(new ActionListener(){
public void actionPerformed(ActionEvent event) {
textAreaSaisie.setText("");
}});
JLabel titre = new JLabel("Chat avec "+ this.destination.getPseudo(),SwingConstants.CENTER);
GridBagConstraints gbc_titre = new GridBagConstraints();
gbc_titre.anchor = GridBagConstraints.NORTH;
gbc_titre.fill = GridBagConstraints.HORIZONTAL;
gbc_titre.insets = new Insets(0, 0, 5, 0);
gbc_titre.gridx = 0;
gbc_titre.gridy = 0;
frame.getContentPane().add(titre, gbc_titre);
// Zone d'affichage de l'historique
this.textAreaAffichage = new JTextArea(10,5);
textAreaAffichage.setLineWrap(true);
this.textAreaAffichage.setText("");
JScrollPane scrollPaneAffichage = new JScrollPane(this.textAreaAffichage);
this.textAreaAffichage.setEditable(false); // il sert juste a afficher
GridBagConstraints gbc_textAreaAffichage = new GridBagConstraints();
gbc_textAreaAffichage.fill = GridBagConstraints.BOTH;
gbc_textAreaAffichage.insets = new Insets(0, 0, 5, 0);
gbc_textAreaAffichage.gridx = 0;
gbc_textAreaAffichage.gridy = 1;
frame.getContentPane().add(scrollPaneAffichage, gbc_textAreaAffichage);
panel.add(BorderLayout.CENTER, scrollPane);
panel.add(BorderLayout.SOUTH,send);
panel.add(BorderLayout.SOUTH,reset);
panel.setLayout(new BoxLayout(panel, BoxLayout.X_AXIS));
//Add the panel to the window.
GridBagConstraints gbc_panel = new GridBagConstraints();
gbc_panel.anchor = GridBagConstraints.NORTH;
gbc_panel.fill = GridBagConstraints.HORIZONTAL;
gbc_panel.gridx = 0;
gbc_panel.gridy = 2;
frame.getContentPane().add(panel, gbc_panel);
/*
*
*JTextArea textAreaAffichage = new JTextArea(10,5);
textAreaAffichage.setEditable(false);
JTextArea textAreaSaisie = new JTextArea(10,5);
textAreaSaisie.setForeground(Color.LIGHT_GRAY);
textAreaSaisie.setFont(new Font("Lucida Grande", Font.ITALIC, 11));
textAreaSaisie.setText("Entrer du texte ici !!!");
JScrollPane scrollPane = new JScrollPane(textAreaSaisie);
JButton send = new JButton("Envoye");
frame.getRootPane().setDefaultButton(send);
send.addActionListener(new ActionListener(){
public void actionPerformed(ActionEvent event) {
//UTILISER TCPENVOI
textAreaSaisie.setText("");
}});
JButton reset = new JButton("Vider");
reset.addActionListener(new ActionListener(){
public void actionPerformed(ActionEvent event) {
textAreaSaisie.setText("");
}});
JLabel titre = new JLabel("Chat avec "+ this.destination.getPseudo(),SwingConstants.CENTER);
panel.add(BorderLayout.CENTER, scrollPane);
//panel.add(scrollPane);
panel.add(BorderLayout.SOUTH,send);
panel.add(BorderLayout.SOUTH,reset);
panel.setLayout(new BoxLayout(panel, BoxLayout.X_AXIS));
//Add the panel to the window.
frame.getContentPane().add(BorderLayout.SOUTH, panel);
frame.getContentPane().add(BorderLayout.CENTER, textAreaAffichage);
frame.getContentPane().add(BorderLayout.NORTH, titre);
*/
}
}

View file

@ -1,256 +0,0 @@
package src.View;
import java.awt.BorderLayout;
import java.awt.Dimension;
import java.awt.GridLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.KeyEvent;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;
import java.util.Vector;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import javax.imageio.ImageIO;
import javax.swing.AbstractAction;
import javax.swing.BorderFactory;
import javax.swing.ImageIcon;
import javax.swing.JButton;
import javax.swing.JComboBox;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JMenu;
import javax.swing.JMenuBar;
import javax.swing.JMenuItem;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JTable;
import javax.swing.JTextArea;
import javax.swing.JTextField;
import javax.swing.SwingConstants;
import src.Controller.*;
import java.awt.Font;
import java.awt.Color;
import java.awt.ComponentOrientation;
import java.awt.SystemColor;
/*
* Classe representant la fenetre de menu. Lance apres la connexion d'un utilisateur
*/
public class View_Menu {
JFrame frame;
JPanel panel;
JMenuBar menu;
ChatApp app;
JLabel jlabel;
JLabel Txt;
WindowAdapter wa ;
/*
* Constructeur d'une fenetre de menu apres la connexion d'un utilisateur.
* @param app Un objet de type ChatApp pour posseder toutes les informations de l'utilisateur
*/
public View_Menu(ChatApp app) {
this.app = app ;
//creer une instance JFrame
frame = new JFrame("ChatApp-AL-NM");
frame.setDefaultCloseOperation(JFrame.DO_NOTHING_ON_CLOSE);
// fixer les dimensions de la fenetre
frame.setSize(new Dimension(394, 344));
// Lorsque l'utilisateur souhaite quitter la fenetre on affiche un pop-up pour verifier son choix
wa = new WindowAdapter(){
public void windowClosing(WindowEvent e){
int reponse = showConfirmDialog();
if (reponse==0){
try {
// on deconnecte l'app avant de quitter
// Tout les utilisateurs sont donc prevenus du depart
app.deconnexion();
} catch (IOException e1) {
e1.printStackTrace();
}
frame.dispose();
}
}};
frame.addWindowListener( wa ) ;
// Menu pour les differentes actions réalisables
menu = new JMenuBar();
//Creation d'un JPanel
panel = new JPanel(new GridLayout(3,1));
panel.setForeground(SystemColor.menuText);
// Ajouter tout les elements a la fenetre
this.addWidgets();
// ajouter le panel a la fenetre
frame.getContentPane().add(panel, BorderLayout.CENTER);
// Afficher la fenetre
frame.pack();
frame.setVisible(true);
}
/**
* Methode static creant un pop-up demandant a l'utilisateur si il souhaite vraiment quitter.
*/
static int showConfirmDialog(){
return JOptionPane.showConfirmDialog(
null,
"Voulez-vous vraiment quitter?",
"Quitter",
JOptionPane.YES_NO_OPTION);
}
/**
* Creer et ajouter les outils de la fenetre
*/
private void addWidgets() {
// On ajoute une jolie icone
jlabel = new JLabel(new ImageIcon("/Users/auriane/Desktop/ChatApp-AL-NM/Implementation/src/images/Logo.png"), JLabel.CENTER);
Txt = new JLabel("Menu principal de " + app.getMe().getPseudo());
Txt.setFont(new Font("Tamil MN", Font.PLAIN, 30));
Txt.setHorizontalAlignment(SwingConstants.CENTER);
//On cree une item Actions que l'on ajoutera a la bar de menu
JMenu Actions = new JMenu("Actions");
Actions.setForeground(Color.WHITE);
Actions.setHorizontalAlignment(SwingConstants.CENTER);
// Définir le sous-menu pour Actions
JMenuItem actifs = new JMenuItem("Utilisateurs actifs");
JMenuItem session = new JMenuItem("Session de Clavardage");
JMenuItem pseudo = new JMenuItem("Modifier Pseudo");
JMenuItem deconnexion = new JMenuItem("Deconnexion");
// Ajouter les sous items a actions
Actions.add(actifs);
Actions.add(session);
Actions.add(pseudo);
Actions.add(deconnexion);
// On ajoute l'item Action dans la bar de menu
menu.add(Actions);
// On ajouter les differents elements au panel
panel.add(BorderLayout.NORTH , menu);
panel.add(BorderLayout.CENTER, jlabel);
panel.add(BorderLayout.SOUTH , Txt );
//******************************************************************************************************************
//**************************************** Actions lorsque l'on clique sur actifs **********************************
//******************************************************************************************************************
actifs.addActionListener( new ActionListener(){
public void actionPerformed(ActionEvent event) {
JPanel panel1 = new JPanel();
JButton home = new JButton(new ImageIcon("/Users/auriane/Desktop/ChatApp-AL-NM/Implementation/src/images/Home.png"));
JTextArea textArea = new JTextArea(20,20);
textArea.insert("Liste Utilisateurs Actifs \n",0);
JScrollPane scrollPane = new JScrollPane(textArea);
String utilisateurs = app.getActifUsers().afficherListeUtilisateurs();
for(String elem : utilisateurs.split("\n")) {
textArea.append( " - " +Utilisateur.stringToUtilisateur(elem).getPseudo() + '\n');
}
panel1.add(textArea);
home.addActionListener(new ActionListener(){
public void actionPerformed(ActionEvent event) {
frame.dispose();
new View_Menu(app);
} });
textArea.setEditable(false);
frame.getContentPane().removeAll();
frame.getContentPane().add(BorderLayout.CENTER, panel1);
frame.getContentPane().add(BorderLayout.NORTH , home);
frame.setVisible(true);
}});
//******************************************************************************************************************
//**************************************** Actions lorsque l'on clique sur Session *********************************
//******************************************************************************************************************
session.addActionListener( new ActionListener(){
public void actionPerformed(ActionEvent event) {
JButton home = new JButton(new ImageIcon("/Users/auriane/Desktop/ChatApp-AL-NM/Implementation/src/images/Home.png"));
home.addActionListener(new ActionListener(){
public void actionPerformed(ActionEvent event) {
frame.dispose();
new View_Menu(app);
} });
String utilisateurs = app.getActifUsers().afficherListeUtilisateurs();
Vector<String> vector = new Vector<String>();
for(String elem : utilisateurs.split("\n")) {
vector.add(elem);
}
// Créer une liste déroulante
JComboBox cb = new JComboBox(vector);
cb.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent event) {
Object selected = cb.getSelectedItem();
new View_Clavardage(app, selected.toString());
}
});
JPanel panel1 = new JPanel(new GridLayout(2,1));
panel1.add(home);
panel1.add(cb);
frame.getContentPane().removeAll();
frame.getContentPane().add(panel1,BorderLayout.CENTER);
frame.setVisible(true);
} });
//******************************************************************************************************************
//**************************************** Actions lorsque l'on clique sur Pseudo **********************************
//******************************************************************************************************************
pseudo.addActionListener( new ActionListener(){
public void actionPerformed(ActionEvent event) {
JLabel Text = new JLabel("Entrez un nouveau nom d'utilisateur!", SwingConstants.CENTER);
JTextField pseudofield = new JTextField(2); // Zone d'insertion de texte
JButton home = new JButton(new ImageIcon("/Users/auriane/Desktop/ChatApp-AL-NM/Implementation/src/images/Home.png"));
home.addActionListener(new ActionListener(){
public void actionPerformed(ActionEvent event) {
frame.dispose();
new View_Menu(app);
} });
//Ajout d'un bouton Valider
JButton Valider = new JButton("Valider");
frame.getRootPane().setDefaultButton(Valider);
//Listen to events from the Valider button.
Valider.addActionListener(new ActionListener(){
public void actionPerformed(ActionEvent event) {
String nouveau = pseudofield.getText();
try {
Boolean resultat = app.modifierPseudo(nouveau);
if(resultat) {
JOptionPane.showMessageDialog(frame, "Modification pseudo Reussi");
frame.dispose();
new View_Menu(app);
}
else {
JOptionPane.showMessageDialog(frame, "Echec Modification pseudo ");
}
} catch (IOException e) {
e.printStackTrace();
}
}
});
JPanel panel1 = new JPanel(new GridLayout(4,1));
panel1.add(home);
panel1.add(Text);
panel1.add(pseudofield);
panel1.add(Valider);
frame.getContentPane().removeAll();
frame.getContentPane().add(panel1,BorderLayout.CENTER);
frame.setVisible(true);
}});
//******************************************************************************************************************
//**************************************** Actions lorsque l'on clique sur Deconnexion *****************************
//******************************************************************************************************************
deconnexion.addActionListener( new ActionListener(){
public void actionPerformed(ActionEvent event) {
frame.dispatchEvent(new WindowEvent(frame, WindowEvent.WINDOW_CLOSING));
} });
}
}

Binary file not shown.

Before

Width:  |  Height:  |  Size: 6.7 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 36 KiB