Skip to content
Snippets Groups Projects
Commit b5e4ddde authored by Paul Ripault's avatar Paul Ripault
Browse files

Initial commit

parents
Branches master
No related tags found
No related merge requests found
Showing
with 724 additions and 0 deletions
*.iml
.gradle
/local.properties
/.idea/caches
/.idea/libraries
/.idea/modules.xml
/.idea/workspace.xml
/.idea/navEditor.xml
/.idea/assetWizardSettings.xml
.DS_Store
/build
/captures
.externalNativeBuild
.cxx
local.properties
# Default ignored files
/shelf/
/workspace.xml
tp5_selection_couleur
\ No newline at end of file
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="CompilerConfiguration">
<bytecodeTargetLevel target="1.8" />
</component>
</project>
\ No newline at end of file
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="GradleMigrationSettings" migrationVersion="1" />
<component name="GradleSettings">
<option name="linkedExternalProjectsSettings">
<GradleProjectSettings>
<option name="testRunner" value="PLATFORM" />
<option name="distributionType" value="DEFAULT_WRAPPED" />
<option name="externalProjectPath" value="$PROJECT_DIR$" />
<option name="modules">
<set>
<option value="$PROJECT_DIR$" />
<option value="$PROJECT_DIR$/app" />
</set>
</option>
<option name="resolveModulePerSourceSet" value="false" />
<option name="useQualifiedModuleNames" value="true" />
</GradleProjectSettings>
</option>
</component>
</project>
\ No newline at end of file
<?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="BintrayJCenter" />
<option name="name" value="BintrayJCenter" />
<option name="url" value="https://jcenter.bintray.com/" />
</remote-repository>
<remote-repository>
<option name="id" value="Google" />
<option name="name" value="Google" />
<option name="url" value="https://dl.google.com/dl/android/maven2/" />
</remote-repository>
</component>
</project>
\ No newline at end of file
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="ProjectRootManager" version="2" languageLevel="JDK_1_8" default="true" project-jdk-name="1.8" project-jdk-type="JavaSDK">
<output url="file://$PROJECT_DIR$/build/classes" />
</component>
<component name="ProjectType">
<option name="id" value="Android" />
</component>
</project>
\ No newline at end of file
/build
\ No newline at end of file
plugins {
id 'com.android.application'
}
android {
compileSdkVersion 30
defaultConfig {
applicationId "fr.ulille.iutinfo.jmplace.pizzaland"
minSdkVersion 16
targetSdkVersion 30
versionCode 1
versionName "1.0"
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
}
buildTypes {
release {
minifyEnabled false
proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
}
}
compileOptions {
sourceCompatibility JavaVersion.VERSION_1_8
targetCompatibility JavaVersion.VERSION_1_8
}
}
dependencies {
implementation 'androidx.appcompat:appcompat:1.2.0'
implementation 'com.google.android.material:material:1.3.0'
implementation 'androidx.constraintlayout:constraintlayout:2.0.4'
implementation 'androidx.navigation:navigation-fragment:2.3.3'
implementation 'androidx.navigation:navigation-ui:2.3.3'
implementation 'androidx.recyclerview:recyclerview-selection:1.1.0'
implementation 'androidx.legacy:legacy-support-v4:1.0.0'
implementation 'androidx.lifecycle:lifecycle-livedata-ktx:2.3.0'
implementation 'androidx.lifecycle:lifecycle-viewmodel-ktx:2.3.0'
testImplementation 'junit:junit:4.+'
androidTestImplementation 'androidx.test.ext:junit:1.1.2'
androidTestImplementation 'androidx.test.espresso:espresso-core:3.3.0'
}
\ No newline at end of file
# Add project specific ProGuard rules here.
# You can control the set of applied configuration files using the
# proguardFiles setting in build.gradle.
#
# For more details, see
# http://developer.android.com/guide/developing/tools/proguard.html
# If your project uses WebView with JS, uncomment the following
# and specify the fully qualified class name to the JavaScript interface
# class:
#-keepclassmembers class fqcn.of.javascript.interface.for.webview {
# public *;
#}
# Uncomment this to preserve the line number information for
# debugging stack traces.
#-keepattributes SourceFile,LineNumberTable
# If you keep the line number information, uncomment this to
# hide the original source file name.
#-renamesourcefileattribute SourceFile
\ No newline at end of file
package fr.ulille.iutinfo.jmplace.pizzadroid;
import android.content.Context;
import androidx.test.platform.app.InstrumentationRegistry;
import androidx.test.ext.junit.runners.AndroidJUnit4;
import org.junit.Test;
import org.junit.runner.RunWith;
import static org.junit.Assert.*;
/**
* Instrumented test, which will execute on an Android device.
*
* @see <a href="http://d.android.com/tools/testing">Testing documentation</a>
*/
@RunWith(AndroidJUnit4.class)
public class ExampleInstrumentedTest {
@Test
public void useAppContext() {
// Context of the app under test.
Context appContext = InstrumentationRegistry.getInstrumentation().getTargetContext();
assertEquals("fr.ulille.iutinfo.jmplace.pizzaland", appContext.getPackageName());
}
}
\ No newline at end of file
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="fr.ulille.iutinfo.jmplace.pizzadroid">
<application
android:allowBackup="true"
android:icon="@mipmap/ic_launcher"
android:label="@string/app_name"
android:roundIcon="@mipmap/ic_launcher_round"
android:supportsRtl="true"
android:theme="@style/Theme.Pizzaland">
<activity
android:name="fr.ulille.iutinfo.jmplace.pizzadroid.MainActivity"
android:label="@string/app_name"
android:theme="@style/Theme.Pizzaland.NoActionBar">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
</application>
</manifest>
\ No newline at end of file
package fr.ulille.iutinfo.jmplace.pizzadroid;
import android.os.Bundle;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.TextView;
import androidx.annotation.NonNull;
import androidx.fragment.app.Fragment;
import androidx.lifecycle.Observer;
import androidx.lifecycle.ViewModelProvider;
import androidx.navigation.fragment.NavHostFragment;
import androidx.recyclerview.widget.LinearLayoutManager;
import androidx.recyclerview.widget.RecyclerView;
import fr.ulille.iutinfo.jmplace.pizzadroid.pizzaland.Pizza;
public class LoggedFragment extends Fragment implements Observer<Integer> {
private PizzaViewModel model;
@Override
public View onCreateView(
LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState
) {
// Inflate the layout for this fragment
return inflater.inflate(R.layout.fragment_logged, container, false);
}
public void onViewCreated(@NonNull View view, Bundle savedInstanceState) {
super.onViewCreated(view, savedInstanceState);
model = new ViewModelProvider(requireActivity()).get(PizzaViewModel.class);
TextView welcome = getActivity().findViewById(R.id.welcome);
String welcomeMsg = getActivity().getResources().getString(R.string.hello, model.getLoggedUser());
welcome.setText(welcomeMsg);
view.findViewById(R.id.button_second).setOnClickListener(view1 -> NavHostFragment.findNavController(LoggedFragment.this)
.navigate(R.id.action_SecondFragment_to_FirstFragment));
// RecyclerView Setup
RecyclerView pizzasList = getActivity().findViewById(R.id.pizzasList);
pizzasList.setLayoutManager(new LinearLayoutManager(getActivity()));
PizzaAdapter adapter = new PizzaAdapter(model);
pizzasList.setAdapter(adapter);
update();
model.observeSelection(this, this);
}
@Override
public void onSaveInstanceState(@NonNull Bundle outState) {
super.onSaveInstanceState(outState);
}
private void update() {
TextView tvMontant = getActivity().findViewById(R.id.etAmount);
tvMontant.setText(getActivity().getResources().getString(R.string.price, model.getPanier().getAmount()));
}
@Override
public void onChanged(Integer integer) {
Log.d("PIZZA", "update logged fragment");
}
}
\ No newline at end of file
package fr.ulille.iutinfo.jmplace.pizzadroid;
import android.os.Bundle;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.EditText;
import android.widget.Toast;
import androidx.annotation.NonNull;
import androidx.fragment.app.Fragment;
import androidx.lifecycle.ViewModelProvider;
import androidx.navigation.fragment.NavHostFragment;
import fr.ulille.iutinfo.jmplace.pizzadroid.pizzaland.Pizza;
public class LoginFragment extends Fragment {
private PizzaViewModel model;
@Override
public View onCreateView(
LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState
) {
// Inflate the layout for this fragment
return inflater.inflate(R.layout.fragment_login, container, false);
}
public void onViewCreated(@NonNull View view, Bundle savedInstanceState) {
super.onViewCreated(view, savedInstanceState);
model = new ViewModelProvider(requireActivity()).get(PizzaViewModel.class);
view.findViewById(R.id.button_first).setOnClickListener(view1 -> {
EditText etLogin = getActivity().findViewById(R.id.etLogin);
EditText etPasswd = getActivity().findViewById(R.id.etPasswd);
if (etPasswd.getText().toString().equals("Doe")) {
model.login(etLogin.getText().toString());
NavHostFragment.findNavController(LoginFragment.this)
.navigate(R.id.action_FirstFragment_to_SecondFragment);
} else {
Toast failed = Toast.makeText(getActivity(), R.string.failed_message, Toast.LENGTH_LONG);
failed.show();
etLogin.setText("");
etPasswd.setText("");
model.logout();
}
});
}
}
\ No newline at end of file
package fr.ulille.iutinfo.jmplace.pizzadroid;
import android.os.Bundle;
import com.google.android.material.floatingactionbutton.FloatingActionButton;
import com.google.android.material.snackbar.Snackbar;
import androidx.appcompat.app.AppCompatActivity;
import androidx.appcompat.widget.Toolbar;
import androidx.lifecycle.ViewModelProvider;
import android.view.View;
import android.view.Menu;
import android.view.MenuItem;
import fr.ulille.iutinfo.jmplace.pizzadroid.pizzaland.Pizza;
public class MainActivity extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
PizzaViewModel model = new ViewModelProvider(this).get(PizzaViewModel.class);
model.setPizzas(Pizza.loadPizzas(this));
Toolbar toolbar = findViewById(R.id.toolbar);
setSupportActionBar(toolbar);
FloatingActionButton fab = findViewById(R.id.fab);
fab.setOnClickListener(view -> Snackbar.make(view, "Replace with your own action", Snackbar.LENGTH_LONG)
.setAction("Action", null).show());
}
@Override
public boolean onCreateOptionsMenu(Menu menu) {
// Inflate the menu; this adds items to the action bar if it is present.
getMenuInflater().inflate(R.menu.menu_main, menu);
return true;
}
@Override
public boolean onOptionsItemSelected(MenuItem item) {
// Handle action bar item clicks here. The action bar will
// automatically handle clicks on the Home/Up button, so long
// as you specify a parent activity in AndroidManifest.xml.
int id = item.getItemId();
//noinspection SimplifiableIfStatement
if (id == R.id.action_settings) {
return true;
}
return super.onOptionsItemSelected(item);
}
}
\ No newline at end of file
package fr.ulille.iutinfo.jmplace.pizzadroid;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.TextView;
import androidx.annotation.NonNull;
import androidx.lifecycle.MutableLiveData;
import androidx.recyclerview.widget.RecyclerView;
import fr.ulille.iutinfo.jmplace.pizzadroid.pizzaland.Pizza;
public class PizzaAdapter extends RecyclerView.Adapter<PizzaAdapter.ViewHolder> {
final PizzaViewModel model;
class ViewHolder extends RecyclerView.ViewHolder {
private final View itemView;
public void setName(String name) {
((TextView) itemView.findViewById(R.id.name)).setText(name);
}
public void setBase(String base) {
((TextView) itemView.findViewById(R.id.base)).setText(base);
}
public void setPriceSmall(double price) {
String formatted = itemView.getContext().getResources().getString(R.string.price, price);
((TextView) itemView.findViewById(R.id.price_small)).setText(formatted);
}
public void setPriceLarge(double price) {
String formatted = itemView.getContext().getResources().getString(R.string.price, price);
((TextView) itemView.findViewById(R.id.price_large)).setText(formatted);
}
public void setQtySmall(int qty) {
((TextView) itemView.findViewById(R.id.qty_small)).setText("" + qty);
}
public void setQtyLarge(int qty) {
((TextView) itemView.findViewById(R.id.qty_large)).setText("" + qty);
}
public TextView getNameView() {
return itemView.findViewById(R.id.name);
}
public TextView getBaseView() {
return itemView.findViewById(R.id.base);
}
public TextView getPriceSmallView() {
return itemView.findViewById(R.id.price_small);
}
public TextView getPriceLargeView() {
return itemView.findViewById(R.id.price_large);
}
public TextView getQtySmallView() {
return itemView.findViewById(R.id.qty_small);
}
public TextView getQtyLargeView() {
return itemView.findViewById(R.id.qty_large);
}
public ViewHolder(@NonNull View itemView) {
super(itemView);
this.itemView = itemView;
this.itemView.setOnClickListener(view -> {
select(getAdapterPosition());
});
}
}
public PizzaAdapter(PizzaViewModel model) {
this.model = model;
}
@NonNull
@Override
public PizzaAdapter.ViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
View view = LayoutInflater.from(parent.getContext())
.inflate(R.layout.pizza_view_holder, parent, false);
return new ViewHolder(view);
}
@Override
public void onBindViewHolder(@NonNull PizzaAdapter.ViewHolder holder, int position) {
Pizza pizza = model.getPizzas()[position];
holder.getNameView().setText(pizza.getNom());
holder.getBaseView().setText(pizza.getBase());
holder.getPriceSmallView().setText("" + pizza.getPriceSmall());
holder.getPriceLargeView().setText("" + pizza.getPriceLarge());
holder.getQtySmallView().setText("" + model.getPanier().getQtySmall(position));
holder.getQtyLargeView().setText("" + model.getPanier().getQtyLarge(position));
if ((model.getSelected() != null)
&& (holder.getAdapterPosition() == model.getSelected())) {
holder.itemView.setActivated(true);
}
else {
holder.itemView.setActivated(false);
}
}
@Override
public int getItemCount() {
return model.getPizzas().length;
}
public void select(Integer position){
model.setSelected(position);
Log.d("PIZZA", "Item " + position + " selected.");
Integer old = model.getSelected();
if (old != null) {
notifyItemChanged(old);
}
model.setSelected(position);
notifyItemChanged(position);
}
}
\ No newline at end of file
package fr.ulille.iutinfo.jmplace.pizzadroid;
import androidx.annotation.MainThread;
import androidx.annotation.NonNull;
import androidx.lifecycle.LifecycleOwner;
import androidx.lifecycle.MutableLiveData;
import androidx.lifecycle.Observer;
import androidx.lifecycle.ViewModel;
import fr.ulille.iutinfo.jmplace.pizzadroid.pizzaland.Panier;
import fr.ulille.iutinfo.jmplace.pizzadroid.pizzaland.Pizza;
public class PizzaViewModel extends ViewModel {
private String loggedUser;
private Pizza[] pizzas;
private Panier panier;
private MutableLiveData<Integer> selected;
public PizzaViewModel() {
this.loggedUser = null;
this.panier = null;
this.selected = null;
}
public void setPizzas(Pizza[] pizzas) {
this.pizzas = pizzas;
}
public String getLoggedUser() {
return this.loggedUser;
}
public void login(String loggedUser) {
this.loggedUser = loggedUser;
this.panier = new Panier(new Pizza[pizzas.length]);
}
public void logout() {
login(null);
}
public Panier getPanier() {
return this.panier;
}
public Pizza[] getPizzas() {
return this.pizzas;
}
public Integer getSelected() {
return getLiveSelected().getValue();
}
public void setSelected(Integer selected) {
getLiveSelected().setValue(selected);
}
private MutableLiveData<Integer> getLiveSelected() {
if (selected == null) {
selected = new MutableLiveData<>();
}
return selected;
}
@MainThread
public void observeSelection(@NonNull LifecycleOwner owner, @NonNull Observer<? super Integer> observer) {
getLiveSelected().observe(owner, observer);
}
}
package fr.ulille.iutinfo.jmplace.pizzadroid.pizzaland;
public class Panier {
private final Pizza[] pizzas ;
private final int[] qtySmall ;
private final int[] qtyLarge ;
public Panier(Pizza[] pizzas) {
this.pizzas = pizzas;
this.qtySmall = new int[pizzas.length];
this.qtyLarge = new int[pizzas.length];
// Initialisations a fin de test: A supprimer en production
this.qtyLarge[1] = 2;
this.qtySmall[2] = 5;
}
public int getQtySmall(int position) {
return this.qtySmall[position];
}
public int getQtyLarge(int position) {
return this.qtyLarge[position];
}
public double getAmount() {
double amount = 0.0;
for (int i = 0; i < pizzas.length; i++) {
amount += qtySmall[i] * pizzas[i].getPrix_petite();
amount += qtyLarge[i] * pizzas[i].getPrix_grande();
}
return amount;
}
}
package fr.ulille.iutinfo.jmplace.pizzadroid.pizzaland;
import android.content.Context;
import android.widget.Toast;
import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import fr.ulille.iutinfo.jmplace.pizzadroid.R;
public class Pizza {
private static Pizza[] pizzas;
private final String id;
private final String nom;
private final String base;
private final double prix_petite;
private final double prix_grande;
private String priceSmall;
private String priceLarge;
public static Pizza[] loadPizzas(Context context) {
pizzas = loadPizzasFromResources(context, R.raw.pizzas);
Pizza.formatPrice(context);
return pizzas;
}
public static Pizza[] loadPizzasFromResources(Context context, int resId) {
StringBuilder text = new StringBuilder();
BufferedReader br = new BufferedReader(new InputStreamReader(context.getResources().openRawResource(resId)));
String line;
try {
while ((line = br.readLine()) != null) {
text.append(line);
text.append('\n');
}
br.close();
JSONArray array = new JSONArray(text.toString());
pizzas = LoadPizzasFromJson(array);
} catch (JSONException | IOException e) {
Toast failedLoad = Toast.makeText(context, R.string.failedLoad, Toast.LENGTH_LONG);
failedLoad.show();
}
return pizzas;
}
private static Pizza[] LoadPizzasFromJson(JSONArray json) throws JSONException {
Pizza[] pizzas = new Pizza[json.length()];
for (int i = 0 ; i < json.length(); i++) {
pizzas[i] = new Pizza(json.getJSONObject(i));
}
return pizzas;
}
public static void formatPrice(Context context) {
for (Pizza p : pizzas) {
p.priceSmall = context.getResources().getString(R.string.price, p.prix_petite);
p.priceLarge = context.getResources().getString(R.string.price, p.prix_grande);
}
}
public String getId() {
return id;
}
public String getNom() {
return nom;
}
public String getBase() {
return base;
}
public double getPrix_petite() {
return prix_petite;
}
public double getPrix_grande() {
return prix_grande;
}
public String getPriceSmall() {
return priceSmall;
}
public String getPriceLarge() {
return priceLarge;
}
private Pizza(JSONObject json) throws JSONException {
this.id = json.getString("id");
this.nom = json.getString("nom");
this.base = json.getString("base");
this.prix_petite = json.getDouble("prix_petite");
this.prix_grande = json.getDouble("prix_grande");
}
}
<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item
android:drawable="@color/white"
android:state_activated="false"
/>
<item
android:drawable="@color/green"
android:state_activated="true"
/>
</selector>
\ No newline at end of file
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment