diff --git a/README.md b/README.md index 9117d9e..9a0c618 100644 --- a/README.md +++ b/README.md @@ -1,7 +1,8 @@ UML Class Editor ---------------- -This app allows you to design an app using UML when you are away from a desktop. Features: +This app allows you to design an app using UML when you are away from a desktop. +### Features: * Main UML notations for Java classes * lass/attribute/method editor @@ -10,6 +11,16 @@ This app allows you to design an app using UML when you are away from a desktop. * Custom types * Standard functionalities such as export, import, merge +## UI +| | | | | +|---------|---------|---------|---------| +| || | | +| | + + + + +## Download apk at release or on [Get it on F-Droid](https://f-droid.org/packages/com.nathaniel.motus.umlclasseditor/) diff --git a/app/build.gradle b/app/build.gradle index ea70d69..753de4f 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -1,14 +1,14 @@ apply plugin: 'com.android.application' android { - compileSdkVersion 29 - + namespace 'com.nathaniel.motus.umlclasseditor' + compileSdkVersion 33 defaultConfig { applicationId "com.nathaniel.motus.umlclasseditor" - minSdkVersion 19 - targetSdkVersion 29 - versionCode 2 - versionName "1.1" + minSdkVersion 21 + targetSdkVersion 33 + versionCode 3 + versionName "1.2" testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner" } @@ -19,17 +19,29 @@ android { proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro' } } + compileOptions { + sourceCompatibility JavaVersion.VERSION_1_8 + targetCompatibility JavaVersion.VERSION_1_8 + } + buildFeatures{ + viewBinding true + } + + allprojects { + gradle.projectsEvaluated { + tasks.withType(JavaCompile) { + options.compilerArgs << "-Xlint:deprecation" + } + } + } } dependencies { - implementation fileTree(dir: "libs", include: ["*.jar"]) - implementation 'androidx.appcompat:appcompat:1.2.0' - implementation 'androidx.constraintlayout:constraintlayout:2.0.4' + implementation 'androidx.appcompat:appcompat:1.6.1' + implementation 'androidx.constraintlayout:constraintlayout:2.1.4' implementation 'androidx.legacy:legacy-support-v4:1.0.0' - testImplementation 'junit:junit:4.12' - androidTestImplementation 'androidx.test.ext:junit:1.1.1' - androidTestImplementation 'androidx.test.espresso:espresso-core:3.2.0' - implementation 'com.google.android.material:material:1.2.1' + implementation 'com.google.android.material:material:1.9.0' + implementation 'androidx.lifecycle:lifecycle-extensions:2.2.0' } diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml index e329be2..f55230b 100644 --- a/app/src/main/AndroidManifest.xml +++ b/app/src/main/AndroidManifest.xml @@ -1,18 +1,24 @@ - + - - + + + - + + diff --git a/app/src/main/java/com/nathaniel/motus/umlclasseditor/App.java b/app/src/main/java/com/nathaniel/motus/umlclasseditor/App.java new file mode 100644 index 0000000..1e9a76d --- /dev/null +++ b/app/src/main/java/com/nathaniel/motus/umlclasseditor/App.java @@ -0,0 +1,38 @@ +package com.nathaniel.motus.umlclasseditor; + +import android.app.Application; +import android.content.Intent; +import android.util.Log; + +import androidx.lifecycle.LifecycleObserver; +import androidx.lifecycle.ProcessLifecycleOwner; + +import com.nathaniel.motus.umlclasseditor.view.CrashActivity; + +import java.io.PrintWriter; +import java.io.StringWriter; + +public class App extends Application implements LifecycleObserver { + private static final String TAG = "App"; + public void onCreate() { + super.onCreate(); + + ProcessLifecycleOwner.get().getLifecycle().addObserver(this); + Thread.setDefaultUncaughtExceptionHandler( + (thread, e) -> { + + + Intent intent = new Intent(getApplicationContext(), CrashActivity.class); + intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK); + StringWriter sw = new StringWriter(); + PrintWriter pw = new PrintWriter(sw); + e.printStackTrace(pw); + String stackTrace = sw.toString(); // stack trace as a string + intent.putExtra("ex", stackTrace); + startActivity(intent); + Log.e(TAG, "uncaughtException: ", e); + System.exit(1); + }); + + } +} \ No newline at end of file diff --git a/app/src/main/java/com/nathaniel/motus/umlclasseditor/controller/IOUtils.java b/app/src/main/java/com/nathaniel/motus/umlclasseditor/controller/IOUtils.java index 68513d0..af701f4 100644 --- a/app/src/main/java/com/nathaniel/motus/umlclasseditor/controller/IOUtils.java +++ b/app/src/main/java/com/nathaniel/motus/umlclasseditor/controller/IOUtils.java @@ -3,13 +3,32 @@ import android.content.Context; import android.content.pm.PackageInfo; import android.content.pm.PackageManager; +import android.graphics.Bitmap; +import android.graphics.Canvas; +import android.graphics.Color; +import android.graphics.Paint; +import android.graphics.pdf.PdfDocument; +import android.media.MediaScannerConnection; import android.net.Uri; +import android.os.Build; +import android.os.Environment; import android.util.Log; +import android.view.View; +import android.widget.Toast; + +import com.nathaniel.motus.umlclasseditor.model.MethodParameter; +import com.nathaniel.motus.umlclasseditor.model.UmlClass; +import com.nathaniel.motus.umlclasseditor.model.UmlClassAttribute; +import com.nathaniel.motus.umlclasseditor.model.UmlClassMethod; +import com.nathaniel.motus.umlclasseditor.model.UmlEnumValue; +import com.nathaniel.motus.umlclasseditor.model.UmlProject; +import com.nathaniel.motus.umlclasseditor.view.GraphView; import java.io.BufferedReader; import java.io.ByteArrayOutputStream; import java.io.File; import java.io.FileInputStream; +import java.io.FileOutputStream; import java.io.FileReader; import java.io.FileWriter; import java.io.IOException; @@ -20,6 +39,9 @@ import java.util.ArrayList; import java.util.Collections; import java.util.Comparator; +import java.util.List; +import java.util.Locale; +import java.util.Objects; public class IOUtils { @@ -113,16 +135,253 @@ public static String readRawHtmlFile(Context context,int rawId) { } return byteArrayOutputStream.toString(); } +// ********************************************************************************************** +// Export PDF +// ********************************************************************************************** + + public static void savePdfToExternalStorage(Context context, GraphView graphView, Uri externalStorageUri) { + + Bitmap main_bitmap = getBitmapFromView(graphView); + PdfDocument document = new PdfDocument(); + PdfDocument.PageInfo pageInfo = new PdfDocument.PageInfo.Builder(main_bitmap.getWidth(), main_bitmap.getHeight(), 1).create(); + PdfDocument.Page page = document.startPage(pageInfo); + + Canvas canvas = page.getCanvas(); + Paint paint = new Paint(); + paint.setColor(Color.WHITE); + canvas.drawPaint(paint); + + Bitmap secondary_bitmap = Bitmap.createScaledBitmap(main_bitmap, main_bitmap.getWidth(), main_bitmap.getHeight(), true); + + paint.setColor(Color.BLACK); + canvas.drawBitmap(secondary_bitmap, 0, 0, null); + + document.finishPage(page); + + try{ + document.writeTo(context.getContentResolver().openOutputStream(externalStorageUri)); + } catch (IOException e) { + Log.e("TEST", Objects.requireNonNull(e.getMessage())); + } finally { + document.close(); + } + + } + + public static Bitmap getBitmapFromView(GraphView view) { + if (view == null) return null; + view.adjustViewToProject(); + boolean drawingCacheEnabled = view.isDrawingCacheEnabled(); + boolean willNotCacheDrawing = view.willNotCacheDrawing(); + view.setDrawingCacheEnabled(true); + view.setWillNotCacheDrawing(false); + Bitmap drawingCache = view.getDrawingCache(); + Bitmap bitmap; + if (null == drawingCache) { + view.measure(View.MeasureSpec.makeMeasureSpec(0, View.MeasureSpec.UNSPECIFIED), + View.MeasureSpec.makeMeasureSpec(0, View.MeasureSpec.UNSPECIFIED)); + view.layout(0, 0, view.getMeasuredWidth(), view.getMeasuredHeight()); + view.buildDrawingCache(); + drawingCache = view.getDrawingCache(); + if (drawingCache != null) { + bitmap = Bitmap.createBitmap(drawingCache); + } else { + bitmap = Bitmap.createBitmap(view.getMeasuredWidth(), view.getMeasuredHeight(), Bitmap.Config.ARGB_8888); + Canvas canvas = new Canvas(bitmap); + view.draw(canvas); + } + } else { + bitmap = Bitmap.createBitmap(drawingCache); + } + view.destroyDrawingCache(); + view.setWillNotCacheDrawing(willNotCacheDrawing); + view.setDrawingCacheEnabled(drawingCacheEnabled); + return bitmap; + + } + +// ********************************************************************************************** +// Code Generation +// ********************************************************************************************** + + public static boolean export2Java(Context context,UmlProject project){ + List list = new ArrayList<>(); + if (project.getUmlClasses().size() == 0) { + Toast.makeText(context, "The project has no existing classes, do make one to generate.", Toast.LENGTH_SHORT).show(); + return false; + } + for (UmlClass umlClass:project.getUmlClasses()){ + StringBuilder javaClass = new StringBuilder(); + switch (umlClass.getUmlClassType()){ + case INTERFACE: + javaClass.append("public interface ").append(umlClass.getName()).append(" {\n"); + javaClass.append(extractAttrib(umlClass.getAttributes())); + javaClass.append(extractMethods(umlClass.getMethods(),true)); + javaClass.append("\n\n}"); + break; + case ENUM: + javaClass.append("public enum ").append(umlClass.getName()).append(" {\n"); + int i=1; + for (UmlEnumValue x:umlClass.getValues()){ + javaClass.append(x.getName()); + if(umlClass.getValues().size() >1 && i!=umlClass.getValues().size()) javaClass.append(","); + javaClass.append("\n"); + i++; + } + javaClass.append("}"); + break; + case ABSTRACT_CLASS: + javaClass.append("public abstract class ").append(umlClass.getName()).append(" {\n"); + javaClass.append(extractAttrib(umlClass.getAttributes())); + javaClass.append(extractMethods(umlClass.getMethods(),false)); + javaClass.append("\n\n}"); + break; + default: + javaClass.append("public class ").append(umlClass.getName()).append(" {\n"); + javaClass.append(extractAttrib(umlClass.getAttributes())); + javaClass.append(extractMethods(umlClass.getMethods(),false)); + javaClass.append("\n\n}"); + break; + } + list.add(saveFiles(context,javaClass.toString(),project.getName(),umlClass.getName())); + } + return !list.contains(false); + } + + static StringBuilder extractAttrib(ArrayList listOfAttrib){ + StringBuilder attrib = new StringBuilder(); + for (UmlClassAttribute x:listOfAttrib){ + attrib.append("\t").append(x.getVisibility().toString().toLowerCase(Locale.ROOT)).append(x.isStatic() ? " static" : "").append(x.isFinal() ? " final" : "").append(" "); + + switch (x.getTypeMultiplicity()){ + case ARRAY: + attrib.append(x.getUmlType().getName()).append("[").append(x.getArrayDimension()).append("]").append(" ").append(x.getName()); + break; + case COLLECTION: + attrib.append("List<").append(x.getUmlType().getName()).append(">").append(" ").append(x.getName()); + break; + default: + attrib.append(x.getUmlType().getName()).append(" ").append(x.getName()); + break; + } + attrib.append(";\n"); + } + + return attrib; + } + + static StringBuilder extractMethods(ArrayList methods,boolean isInterface){ + StringBuilder meths = new StringBuilder(); + for (UmlClassMethod x:methods){ + meths.append(x.getVisibility().toString().toLowerCase(Locale.ROOT)).append(x.isStatic()?" static":"").append(" "); + switch (x.getTypeMultiplicity()){ + case COLLECTION: + meths.append("List<").append(x.getUmlType().getName()).append("> ").append(x.getName()); + break; + case ARRAY: + meths.append(x.getUmlType().getName()).append("[] ").append(x.getName()); + break; + default: + meths.append(x.getUmlType().getName()).append(" ").append(x.getName()); + break; + } + if(!isInterface){ + if(x.getParameterCount()==0) meths.append("() {"); + else{ + meths.append("("); + int i = 1; + for (MethodParameter y:x.getParameters()){ + meths.append(y.getUmlType().getName()).append(" ").append(y.getName()); + if(x.getParameters().size()>1 && i != x.getParameters().size()) meths.append(","); + i++; + } + meths.append(") {"); + } + if(!x.getUmlType().getName().equalsIgnoreCase("void")){ + String type = x.getUmlType().getName(); + if(type.equalsIgnoreCase("int")|| + type.equalsIgnoreCase("double")|| + type.equalsIgnoreCase("float")|| + type.equalsIgnoreCase("long") + ) + meths.append("return 0;"); + else if(type.equalsIgnoreCase("boolean")) meths.append("\nreturn false;"); + else meths.append("\nreturn null;"); + + }else{ + meths.append("\n// please complete your code"); + } + meths.append("\n"); + meths.append(" }\n"); + }else{ + meths.append("("); + int i = 1; + for (MethodParameter y:x.getParameters()){ + meths.append(y.getUmlType().getName()).append(" ").append(y.getName()); + if(x.getParameters().size()>1 && i != x.getParameters().size()) meths.append(","); + i++; + } + meths.append(");\n"); + + } + } + + return meths; + } + + static boolean saveFiles(Context context, String data,String projectName, String name) { + try { + String state = Environment.getExternalStorageState(); + if (Environment.MEDIA_MOUNTED.equals(state)) { + File dir = Environment.getExternalStorageDirectory(); + + File base = new File(dir, "UML Class Editor"); + if (!base.exists()) { + if (!base.mkdirs()) { + Log.e("TEST", "Failed to create directory"); + return false; + } + } + File folder = new File(base, projectName); + if (!folder.exists()) { + if (!folder.mkdirs()) { + Log.e("TEST", "Failed to create directory"); + return false; + } + } + + File file = new File(folder, name + ".java"); + FileOutputStream outputStream = new FileOutputStream(file); + outputStream.write(data.getBytes()); + outputStream.close(); + MediaScannerConnection.scanFile(context, new String[]{file.getAbsolutePath()}, null, null); + + Log.i("IOUtils", "File saved: " + file.getAbsolutePath()); + return true; + } else { + Log.e("IOUtils", "External storage not available for writing"); + return false; + } + } catch (IOException e) { + Log.e("TEST", e.getMessage(), e); + return false; + } + } + // ********************************************************************************************** // Side utilities // ********************************************************************************************** public static int getAppVersionCode(Context context) { - PackageManager manager=context.getPackageManager(); + PackageManager manager = context.getPackageManager(); try { - PackageInfo info = manager.getPackageInfo(context.getPackageName(),0); - return info.versionCode; + PackageInfo info = manager.getPackageInfo(context.getPackageName(), PackageManager.GET_META_DATA); + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.P) { + return (int) info.getLongVersionCode(); + } else { + return info.versionCode; + } } catch (PackageManager.NameNotFoundException e) { return -1; } diff --git a/app/src/main/java/com/nathaniel/motus/umlclasseditor/controller/MainActivity.java b/app/src/main/java/com/nathaniel/motus/umlclasseditor/controller/MainActivity.java index 72e550c..f8837d8 100644 --- a/app/src/main/java/com/nathaniel/motus/umlclasseditor/controller/MainActivity.java +++ b/app/src/main/java/com/nathaniel/motus/umlclasseditor/controller/MainActivity.java @@ -1,42 +1,54 @@ package com.nathaniel.motus.umlclasseditor.controller; +import static android.provider.Settings.ACTION_MANAGE_APP_ALL_FILES_ACCESS_PERMISSION; + import android.Manifest; -import android.app.AlertDialog; import android.content.Context; -import android.content.DialogInterface; import android.content.Intent; import android.content.SharedPreferences; import android.content.pm.PackageManager; +import android.graphics.Bitmap; import android.net.Uri; import android.os.Build; import android.os.Bundle; +import android.os.Environment; +import android.os.Handler; import android.text.Html; import android.util.Log; import android.util.SparseBooleanArray; import android.view.Menu; import android.view.MenuItem; +import android.view.View; import android.widget.AbsListView; import android.widget.ArrayAdapter; import android.widget.EditText; import android.widget.FrameLayout; +import android.widget.ImageView; import android.widget.ListView; +import android.widget.ProgressBar; import android.widget.Spinner; import android.widget.TextView; import android.widget.Toast; import androidx.activity.OnBackPressedCallback; +import androidx.activity.result.ActivityResultLauncher; +import androidx.activity.result.contract.ActivityResultContracts; import androidx.annotation.NonNull; -import androidx.annotation.Nullable; import androidx.annotation.RequiresApi; import androidx.appcompat.app.ActionBarDrawerToggle; +import androidx.appcompat.app.AlertDialog; import androidx.appcompat.app.AppCompatActivity; import androidx.appcompat.widget.Toolbar; +import androidx.core.app.ActivityCompat; +import androidx.core.content.ContextCompat; import androidx.core.view.GravityCompat; import androidx.core.view.MenuCompat; import androidx.drawerlayout.widget.DrawerLayout; import androidx.fragment.app.Fragment; +import com.google.android.material.dialog.MaterialAlertDialogBuilder; import com.google.android.material.navigation.NavigationView; +import com.nathaniel.motus.umlclasseditor.BuildConfig; import com.nathaniel.motus.umlclasseditor.R; import com.nathaniel.motus.umlclasseditor.model.TypeNameComparator; import com.nathaniel.motus.umlclasseditor.model.UmlClass; @@ -58,26 +70,31 @@ public class MainActivity extends AppCompatActivity implements FragmentObserver, GraphView.GraphViewObserver, - NavigationView.OnNavigationItemSelectedListener{ + NavigationView.OnNavigationItemSelectedListener { + private static final String TAG = "MainActivity"; private UmlProject mProject; - private boolean mExpectingTouchLocation=false; - private Purpose mPurpose= FragmentObserver.Purpose.NONE; + private boolean mExpectingTouchLocation = false; + private Purpose mPurpose = FragmentObserver.Purpose.NONE; private Toolbar mToolbar; + private static Toolbar staticToolbar; private DrawerLayout mDrawerLayout; private NavigationView mNavigationView; private TextView mMenuHeaderProjectNameText; - private static boolean sWriteExternalStoragePermission =true; - private static boolean sReadExternalStoragePermission=true; - private static final int WRITE_EXTERNAL_STORAGE_INDEX=0; - private static final int READ_EXTERNAL_STORAGE_INDEX=1; + private static boolean sWriteExternalStoragePermission = true; + private static boolean sReadExternalStoragePermission = true; + private static boolean sManageExternalStoragePermission = true; + private static final int WRITE_EXTERNAL_STORAGE_INDEX = 0; + private static final int READ_EXTERNAL_STORAGE_INDEX = 1; + private static final int MANAGE_EXTERNAL_STORAGE_INDEX = 0; // tiramisu - private long mFirstBackPressedTime =0; - private static long DOUBLE_BACK_PRESSED_DELAY=2000; + private long mFirstBackPressedTime = 0; + private static long DOUBLE_BACK_PRESSED_DELAY = 2000; private OnBackPressedCallback mOnBackPressedCallback; + private AlertDialog dialog = null; -// ********************************************************************************************** + // ********************************************************************************************** // Fragments declaration // ********************************************************************************************** private GraphFragment mGraphFragment; @@ -86,22 +103,22 @@ public class MainActivity extends AppCompatActivity implements FragmentObserver, private MethodEditorFragment mMethodEditorFragment; private ParameterEditorFragment mParameterEditorFragment; - private static final String GRAPH_FRAGMENT_TAG="graphFragment"; - private static final String CLASS_EDITOR_FRAGMENT_TAG="classEditorFragment"; - private static final String ATTRIBUTE_EDITOR_FRAGMENT_TAG="attributeEditorFragment"; - private static final String METHOD_EDITOR_FRAGMENT_TAG="methodEditorFragment"; - private static final String PARAMETER_EDITOR_FRAGMENT_TAG="parameterEditorFragment"; + private static final String GRAPH_FRAGMENT_TAG = "graphFragment"; + private static final String CLASS_EDITOR_FRAGMENT_TAG = "classEditorFragment"; + private static final String ATTRIBUTE_EDITOR_FRAGMENT_TAG = "attributeEditorFragment"; + private static final String METHOD_EDITOR_FRAGMENT_TAG = "methodEditorFragment"; + private static final String PARAMETER_EDITOR_FRAGMENT_TAG = "parameterEditorFragment"; - private static final String SHARED_PREFERENCES_PROJECT_NAME="sharedPreferencesProjectName"; + private static final String SHARED_PREFERENCES_PROJECT_NAME = "sharedPreferencesProjectName"; - private static final int INTENT_CREATE_DOCUMENT_EXPORT_PROJECT =1000; - private static final int INTENT_OPEN_DOCUMENT_IMPORT_PROJECT =2000; - private static final int INTENT_CREATE_DOCUMENT_EXPORT_CUSTOM_TYPES=3000; - private static final int INTENT_OPEN_DOCUMENT_IMPORT_CUSTOM_TYPES=4000; + private static final int INTENT_CREATE_DOCUMENT_EXPORT_PROJECT = 1000; + private static final int INTENT_OPEN_DOCUMENT_IMPORT_PROJECT = 2000; + private static final int INTENT_CREATE_DOCUMENT_EXPORT_CUSTOM_TYPES = 3000; + private static final int INTENT_OPEN_DOCUMENT_IMPORT_CUSTOM_TYPES = 4000; - private static final int REQUEST_PERMISSION=5000; + private static final int REQUEST_PERMISSION = 5000; -// ********************************************************************************************** + // ********************************************************************************************** // Views declaration // ********************************************************************************************** private FrameLayout mMainActivityFrame; @@ -114,7 +131,7 @@ protected void onCreate(Bundle savedInstanceState) { setContentView(R.layout.activity_main); //Instantiate views - mMainActivityFrame=findViewById(R.id.activity_main_frame); + mMainActivityFrame = findViewById(R.id.activity_main_frame); UmlType.clearUmlTypes(); UmlType.initializePrimitiveUmlTypes(this); @@ -130,8 +147,8 @@ protected void onCreate(Bundle savedInstanceState) { @Override public boolean onCreateOptionsMenu(Menu menu) { - getMenuInflater().inflate(R.menu.activity_main_toolbar_menu,menu); - MenuCompat.setGroupDividerEnabled(menu,true); + getMenuInflater().inflate(R.menu.activity_main_toolbar_menu, menu); + MenuCompat.setGroupDividerEnabled(menu, true); return super.onCreateOptionsMenu(menu); } @@ -139,9 +156,8 @@ public boolean onCreateOptionsMenu(Menu menu) { protected void onStart() { super.onStart(); - mGraphView=findViewById(R.id.graphview); + mGraphView = findViewById(R.id.graphview); mGraphView.setUmlProject(mProject); - Log.i("TEST","onStart"); } @Override @@ -149,11 +165,16 @@ protected void onDestroy() { super.onDestroy(); mProject.save(getApplicationContext()); - Log.i("TEST","save : project"); savePreferences(); - Log.i("TEST", "save : preferences"); UmlType.saveCustomUmlTypes(this); - Log.i("TEST","save : custom types"); + } + + @Override + protected void onPause() { + super.onPause(); + mProject.save(getApplicationContext()); + savePreferences(); + UmlType.saveCustomUmlTypes(this); } @RequiresApi(api = Build.VERSION_CODES.M) @@ -168,48 +189,66 @@ protected void onResume() { // ********************************************************************************************** private void configureToolbar() { - mToolbar=findViewById(R.id.main_activity_toolbar); + mToolbar = findViewById(R.id.main_activity_toolbar); + staticToolbar = mToolbar; setSupportActionBar(mToolbar); } private void configureDrawerLayout() { - mDrawerLayout=findViewById(R.id.activity_main_drawer); + mDrawerLayout = findViewById(R.id.activity_main_drawer); ActionBarDrawerToggle toggle = new ActionBarDrawerToggle(this, mDrawerLayout, mToolbar, R.string.navigation_drawer_open, R.string.navigation_drawer_close); mDrawerLayout.addDrawerListener(toggle); toggle.syncState(); } private void configureNavigationView() { - mNavigationView=findViewById(R.id.activity_main_navigation_view); - mMenuHeaderProjectNameText= mNavigationView.getHeaderView(0).findViewById(R.id.activity_main_navigation_view_header_project_name_text); + mNavigationView = findViewById(R.id.activity_main_navigation_view); + mMenuHeaderProjectNameText = mNavigationView.getHeaderView(0).findViewById(R.id.activity_main_navigation_view_header_project_name_text); updateNavigationView(); mNavigationView.setNavigationItemSelectedListener(this); + + // project name click listener + mMenuHeaderProjectNameText.setOnClickListener(v -> { + final EditText editText = new EditText(this); + String oldName = mProject.getName(); + editText.setText(mProject.getName()); + dialog = new MaterialAlertDialogBuilder(this) + .setTitle("Rename") + .setMessage("Enter new name :") + .setView(editText) + .setNegativeButton("CANCEL", (d, i) -> dialog.dismiss()) + .setPositiveButton("OK", (d, i) -> { + renameProject(oldName, editText.getText().toString()); + updateNavigationView(); + }) + .show(); + }); } private void updateNavigationView() { - mMenuHeaderProjectNameText.setText(mProject.getName()); + mMenuHeaderProjectNameText.setText(mProject.getName() + ""); } private void savePreferences() { SharedPreferences preferences = getPreferences(MODE_PRIVATE); - SharedPreferences.Editor editor=preferences.edit(); - editor.putString(SHARED_PREFERENCES_PROJECT_NAME,mProject.getName()); + SharedPreferences.Editor editor = preferences.edit(); + editor.putString(SHARED_PREFERENCES_PROJECT_NAME, mProject.getName()); editor.apply(); } private void getPreferences() { - SharedPreferences preferences=getPreferences(MODE_PRIVATE); - String projectName=preferences.getString(SHARED_PREFERENCES_PROJECT_NAME,null); - Log.i("TEST","Loaded preferences"); + SharedPreferences preferences = getPreferences(MODE_PRIVATE); + String projectName = preferences.getString(SHARED_PREFERENCES_PROJECT_NAME, null); + Log.d(TAG, "getPreferences: "); if (projectName != null) { mProject = UmlProject.load(getApplicationContext(), projectName); } else { - mProject=new UmlProject("NewProject",getApplicationContext()); + mProject = new UmlProject("NewProject", getApplicationContext()); } } private void createOnBackPressedCallback() { - mOnBackPressedCallback=new OnBackPressedCallback(true) { + mOnBackPressedCallback = new OnBackPressedCallback(true) { @Override public void handleOnBackPressed() { onBackButtonPressed(); @@ -218,41 +257,40 @@ public void handleOnBackPressed() { } private void setOnBackPressedCallback() { - this.getOnBackPressedDispatcher().addCallback(this,mOnBackPressedCallback); + this.getOnBackPressedDispatcher().addCallback(this, mOnBackPressedCallback); } private void onBackButtonPressed() { if (Calendar.getInstance().getTimeInMillis() - mFirstBackPressedTime > DOUBLE_BACK_PRESSED_DELAY) { - mFirstBackPressedTime=Calendar.getInstance().getTimeInMillis(); - Toast.makeText(this,"Press back again to leave",Toast.LENGTH_SHORT).show(); - }else + mFirstBackPressedTime = Calendar.getInstance().getTimeInMillis(); + Toast.makeText(this, "Press back again to leave", Toast.LENGTH_SHORT).show(); + } else finish(); } -// ********************************************************************************************** + // ********************************************************************************************** // Fragment management // ********************************************************************************************** - private void configureAndDisplayGraphFragment(int viewContainerId){ + private void configureAndDisplayGraphFragment(int viewContainerId) { //handle graph fragment // mGraphFragment=new GraphFragment(); - mGraphFragment=GraphFragment.newInstance(); + mGraphFragment = GraphFragment.newInstance(); getSupportFragmentManager().beginTransaction() - .replace(viewContainerId,mGraphFragment,GRAPH_FRAGMENT_TAG) + .replace(viewContainerId, mGraphFragment, GRAPH_FRAGMENT_TAG) .commitNow(); } - private void configureAndDisplayClassEditorFragment(int viewContainerId,float xLocation,float yLocation,int classOrder) { + private void configureAndDisplayClassEditorFragment(int viewContainerId, float xLocation, float yLocation, int classOrder) { //handle class editor fragment - if (mClassEditorFragment==null) { + if (mClassEditorFragment == null) { mClassEditorFragment = ClassEditorFragment.newInstance(xLocation, yLocation, classOrder); getSupportFragmentManager().beginTransaction() .hide(mGraphFragment) .add(viewContainerId, mClassEditorFragment, CLASS_EDITOR_FRAGMENT_TAG) .commitNow(); - } - else { + } else { mClassEditorFragment.updateClassEditorFragment(xLocation, yLocation, classOrder); getSupportFragmentManager().beginTransaction() .hide(mGraphFragment) @@ -261,7 +299,7 @@ private void configureAndDisplayClassEditorFragment(int viewContainerId,float xL } } - private void configureAndDisplayAttributeEditorFragment(int viewContainerId,int attributeOrder,int classOrder) { + private void configureAndDisplayAttributeEditorFragment(int viewContainerId, int attributeOrder, int classOrder) { if (mAttributeEditorFragment == null) { mAttributeEditorFragment = AttributeEditorFragment.newInstance(mClassEditorFragment.getTag(), attributeOrder, classOrder); @@ -270,15 +308,15 @@ private void configureAndDisplayAttributeEditorFragment(int viewContainerId,int .add(viewContainerId, mAttributeEditorFragment, ATTRIBUTE_EDITOR_FRAGMENT_TAG) .commitNow(); } else { - mAttributeEditorFragment.updateAttributeEditorFragment(attributeOrder,classOrder); + mAttributeEditorFragment.updateAttributeEditorFragment(attributeOrder, classOrder); getSupportFragmentManager().beginTransaction() .hide(mClassEditorFragment) .show(mAttributeEditorFragment) - .commitNow(); + .commitNow(); } } - private void configureAndDisplayMethodEditorFragment(int viewContainerId, int methodOrder,int classOrder) { + private void configureAndDisplayMethodEditorFragment(int viewContainerId, int methodOrder, int classOrder) { if (mMethodEditorFragment == null) { mMethodEditorFragment = MethodEditorFragment.newInstance(mClassEditorFragment.getTag(), methodOrder, classOrder); getSupportFragmentManager().beginTransaction() @@ -286,7 +324,7 @@ private void configureAndDisplayMethodEditorFragment(int viewContainerId, int me .add(viewContainerId, mMethodEditorFragment, METHOD_EDITOR_FRAGMENT_TAG) .commitNow(); } else { - mMethodEditorFragment.updateMethodEditorFragment(methodOrder,classOrder); + mMethodEditorFragment.updateMethodEditorFragment(methodOrder, classOrder); getSupportFragmentManager().beginTransaction() .hide(mClassEditorFragment) .show(mMethodEditorFragment) @@ -294,7 +332,7 @@ private void configureAndDisplayMethodEditorFragment(int viewContainerId, int me } } - private void configureAndDisplayParameterEditorFragment(int viewContainerId, int parameterOrder,int methodOrder,int classOrder) { + private void configureAndDisplayParameterEditorFragment(int viewContainerId, int parameterOrder, int methodOrder, int classOrder) { if (mParameterEditorFragment == null) { mParameterEditorFragment = ParameterEditorFragment.newInstance(mMethodEditorFragment.getTag(), parameterOrder, methodOrder, classOrder); getSupportFragmentManager().beginTransaction() @@ -302,7 +340,7 @@ private void configureAndDisplayParameterEditorFragment(int viewContainerId, int .add(viewContainerId, mParameterEditorFragment, PARAMETER_EDITOR_FRAGMENT_TAG) .commitNow(); } else { - mParameterEditorFragment.updateParameterEditorFragment(parameterOrder,methodOrder,classOrder); + mParameterEditorFragment.updateParameterEditorFragment(parameterOrder, methodOrder, classOrder); getSupportFragmentManager().beginTransaction() .hide(mMethodEditorFragment) .show(mParameterEditorFragment) @@ -326,7 +364,7 @@ public void setProject(UmlProject project) { @Override public void setPurpose(Purpose purpose) { - mPurpose=purpose; + mPurpose = purpose; } @Override @@ -366,18 +404,18 @@ public void closeParameterEditorFragment(Fragment fragment) { } @Override - public void openAttributeEditorFragment(int attributeOrder,int classOrder) { - configureAndDisplayAttributeEditorFragment(R.id.activity_main_frame,attributeOrder,classOrder); + public void openAttributeEditorFragment(int attributeOrder, int classOrder) { + configureAndDisplayAttributeEditorFragment(R.id.activity_main_frame, attributeOrder, classOrder); } @Override - public void openMethodEditorFragment(int methodOrder,int classOrder) { - configureAndDisplayMethodEditorFragment(R.id.activity_main_frame,methodOrder,classOrder); + public void openMethodEditorFragment(int methodOrder, int classOrder) { + configureAndDisplayMethodEditorFragment(R.id.activity_main_frame, methodOrder, classOrder); } @Override - public void openParameterEditorFragment(int parameterOrder,int methodOrder,int classOrder) { - configureAndDisplayParameterEditorFragment(R.id.activity_main_frame,parameterOrder,methodOrder,classOrder); + public void openParameterEditorFragment(int parameterOrder, int methodOrder, int classOrder) { + configureAndDisplayParameterEditorFragment(R.id.activity_main_frame, parameterOrder, methodOrder, classOrder); } @Override @@ -394,18 +432,18 @@ public boolean isExpectingTouchLocation() { @Override public void createClass(float xLocation, float yLocation) { - configureAndDisplayClassEditorFragment(R.id.activity_main_frame,xLocation,yLocation,-1); + configureAndDisplayClassEditorFragment(R.id.activity_main_frame, xLocation, yLocation, -1); } @Override public void editClass(UmlClass umlClass) { - configureAndDisplayClassEditorFragment(R.id.activity_main_frame,0,0,umlClass.getClassOrder()); + configureAndDisplayClassEditorFragment(R.id.activity_main_frame, 0, 0, umlClass.getClassOrder()); } @Override public void createRelation(UmlClass startClass, UmlClass endClass, UmlRelation.UmlRelationType relationType) { - if (!mProject.relationAlreadyExistsBetween(startClass,endClass)) - mProject.addUmlRelation(new UmlRelation(startClass,endClass,relationType)); + if (!mProject.relationAlreadyExistsBetween(startClass, endClass)) + mProject.addUmlRelation(new UmlRelation(startClass, endClass, relationType)); } // ********************************************************************************************** @@ -414,7 +452,7 @@ public void createRelation(UmlClass startClass, UmlClass endClass, UmlRelation.U @Override public boolean onNavigationItemSelected(@NonNull MenuItem item) { - int menuId=item.getItemId(); + int menuId = item.getItemId(); if (menuId == R.id.drawer_menu_new_project) { drawerMenuNewProject(); } else if (menuId == R.id.drawer_menu_load_project) { @@ -436,32 +474,13 @@ public boolean onNavigationItemSelected(@NonNull MenuItem item) { // ********************************************************************************************** private void drawerMenuSaveAs() { - AlertDialog.Builder builder=new AlertDialog.Builder(this); - final EditText editText=new EditText(this); - editText.setText(mProject.getName()); - builder.setTitle("Save as") - .setMessage("Enter new name :") - .setView(editText) - .setNegativeButton("CANCEL", new DialogInterface.OnClickListener() { - @Override - public void onClick(DialogInterface dialogInterface, int i) { - - } - }) - .setPositiveButton("OK", new DialogInterface.OnClickListener() { - @Override - public void onClick(DialogInterface dialogInterface, int i) { - saveAs(editText.getText().toString()); - } - }) - .create() - .show(); + saveAs(); } private void drawerMenuNewProject() { mProject.save(this); UmlType.clearProjectUmlTypes(); - mProject=new UmlProject("NewProject",this); + mProject = new UmlProject("NewProject", this); mGraphView.setUmlProject(mProject); updateNavigationView(); } @@ -469,118 +488,81 @@ private void drawerMenuNewProject() { private void drawerMenuLoadProject() { mProject.save(this); - final Spinner spinner=new Spinner(this); + final Spinner spinner = new Spinner(this); spinner.setAdapter(projectDirectoryAdapter()); - AlertDialog.Builder builder=new AlertDialog.Builder(this); - builder.setTitle("Load project") + dialog = new MaterialAlertDialogBuilder(this) + .setTitle("Load project") .setMessage("Choose project to load :") .setView(spinner) - .setNegativeButton("CANCEL", new DialogInterface.OnClickListener() { - @Override - public void onClick(DialogInterface dialogInterface, int i) { - + .setNegativeButton("CANCEL", (d, i) -> dialog.dismiss()) + .setPositiveButton("OK", (d, i) -> { + String fileName = spinner.getSelectedItem().toString(); + if (fileName != null) { + UmlType.clearProjectUmlTypes(); + mProject = UmlProject.load(getApplicationContext(), fileName); + mGraphView.setUmlProject(mProject); + updateNavigationView(); + dialog.dismiss(); } }) - .setPositiveButton("OK", new DialogInterface.OnClickListener() { - @Override - public void onClick(DialogInterface dialogInterface, int i) { - String fileName=spinner.getSelectedItem().toString(); - if (fileName!=null) { - UmlType.clearProjectUmlTypes(); - mProject = UmlProject.load(getApplicationContext(), fileName); - mGraphView.setUmlProject(mProject); - updateNavigationView(); - } - } - }) - .create() .show(); } private void drawerMenuDeleteProject() { - - final Context context=this; - - final Spinner spinner=new Spinner(this); + final Spinner spinner = new Spinner(this); spinner.setAdapter(projectDirectoryAdapter()); - - AlertDialog.Builder builder=new AlertDialog.Builder(this); - builder.setTitle("Delete project") + dialog = new MaterialAlertDialogBuilder(this) + .setTitle("Delete project") .setMessage("Choose project to delete :") .setView(spinner) - .setNegativeButton("CANCEL", new DialogInterface.OnClickListener() { - @Override - public void onClick(DialogInterface dialogInterface, int i) { + .setNegativeButton("Cancel", (dialogInterface, i) -> { - } }) - .setPositiveButton("OK", new DialogInterface.OnClickListener() { - @Override - public void onClick(DialogInterface dialogInterface, int i) { - String fileName=spinner.getSelectedItem().toString(); - if (fileName!=null) { - File pathName=new File(getFilesDir(),UmlProject.PROJECT_DIRECTORY); - final File file=new File(pathName,fileName); - AlertDialog.Builder alert=new AlertDialog.Builder(context); - alert.setTitle("Delete Project") - .setMessage("Are you sure you want to delete "+fileName+" ?") - .setNegativeButton("NO", new DialogInterface.OnClickListener() { - @Override - public void onClick(DialogInterface dialogInterface, int i) { - - } - }) - .setPositiveButton("YES", new DialogInterface.OnClickListener() { - @Override - public void onClick(DialogInterface dialogInterface, int i) { - file.delete(); - } - }) - .create() - .show(); - } + .setPositiveButton("OK", (dialogInterface, i) -> { + String fileName = spinner.getSelectedItem().toString(); + if (fileName != null) { + File pathName = new File(getFilesDir(), UmlProject.PROJECT_DIRECTORY); + final File file = new File(pathName, fileName); + dialog = new MaterialAlertDialogBuilder(this) + .setTitle("Delete Project") + .setMessage("Are you sure you want to delete " + fileName + " ?") + .setNegativeButton("NO", (d, i12) -> dialog.dismiss()) + .setPositiveButton("YES", (d, i1) -> { + if (file.delete()) dialog.dismiss(); + }) + .show(); } }) - .create() .show(); } private void drawerMenuMerge() { - final Spinner spinner=new Spinner(this); + final Spinner spinner = new Spinner(this); spinner.setAdapter(projectDirectoryAdapter()); - final Context currentContext=this; - - AlertDialog.Builder builder=new AlertDialog.Builder(this); - builder.setTitle("Merge project") + new MaterialAlertDialogBuilder(this) + .setTitle("Merge project") .setMessage("Choose project to merge") .setView(spinner) - .setNegativeButton("CANCEL", new DialogInterface.OnClickListener() { - @Override - public void onClick(DialogInterface dialogInterface, int i) { - - } + .setNegativeButton("Cancel", (d, i) -> { + d.dismiss(); }) - .setPositiveButton("OK", new DialogInterface.OnClickListener() { - @Override - public void onClick(DialogInterface dialogInterface, int i) { - String fileName=spinner.getSelectedItem().toString(); - if (fileName!=null) { - UmlProject project = UmlProject.load(getApplicationContext(), fileName); - mProject.mergeWith(project); - mGraphView.invalidate(); - } - + .setPositiveButton("OK", (d, i) -> { + String fileName = spinner.getSelectedItem().toString(); + if (fileName != null) { + UmlProject project = UmlProject.load(getApplicationContext(), fileName); + mProject.mergeWith(project); + mGraphView.invalidate(); } + }) - .create() .show(); } private ArrayAdapter projectDirectoryAdapter() { //Create an array adapter to set a spinner with all project file names - ArrayAdapter adapter=new ArrayAdapter<>(this, android.R.layout.simple_spinner_item,IOUtils.sortedFiles(new File(getFilesDir(),UmlProject.PROJECT_DIRECTORY))); + ArrayAdapter adapter = new ArrayAdapter<>(this, android.R.layout.simple_spinner_item, IOUtils.sortedFiles(new File(getFilesDir(), UmlProject.PROJECT_DIRECTORY))); adapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item); return adapter; } @@ -592,8 +574,14 @@ private ArrayAdapter projectDirectoryAdapter() { public boolean onOptionsItemSelected(MenuItem menuItem) { int itemId = menuItem.getItemId(); if (itemId == R.id.toolbar_menu_export) { - if(sWriteExternalStoragePermission) + if (sWriteExternalStoragePermission) menuItemExport(); + } else if (itemId == R.id.toolbar_menu_export_pdf) { + if (sWriteExternalStoragePermission) + menuExportPdf(); + } else if (itemId == R.id.toolbar_menu_export2java) { + if (sWriteExternalStoragePermission) + menuExport2Java(); } else if (itemId == R.id.toolbar_menu_import) { if (sReadExternalStoragePermission) menuItemImport(); @@ -618,162 +606,218 @@ public boolean onOptionsItemSelected(MenuItem menuItem) { // ********************************************************************************************** private void menuItemExport() { - Intent intent=new Intent(Intent.ACTION_CREATE_DOCUMENT); - intent.setType("text/*"); - startActivityForResult(intent, INTENT_CREATE_DOCUMENT_EXPORT_PROJECT); + Intent intent = new Intent(Intent.ACTION_CREATE_DOCUMENT); + intent.setType("application/json"); + intent.putExtra(Intent.EXTRA_TITLE, mProject.getName() + ".json"); + exportProjectLauncher.launch(intent); + } + + private void menuExportPdf() { + Bitmap bitmap = IOUtils.getBitmapFromView(this.mGraphView); + ImageView prev = new ImageView(this); + prev.setImageBitmap(bitmap); + new MaterialAlertDialogBuilder(this) + .setTitle("Preview") + .setView(prev) + .setNegativeButton("Cancel", (d, i) -> d.dismiss()) + .setPositiveButton("Export", (d, i) -> { + Intent intent = new Intent(Intent.ACTION_CREATE_DOCUMENT); + intent.setType("application/pdf"); + exportPDFLauncher.launch(intent); + }) + .show(); } private void menuItemImport() { - Intent intent=new Intent(Intent.ACTION_OPEN_DOCUMENT); + Intent intent = new Intent(Intent.ACTION_OPEN_DOCUMENT); intent.setType("*/*"); - startActivityForResult(intent, INTENT_OPEN_DOCUMENT_IMPORT_PROJECT); + intent.putExtra(Intent.EXTRA_MIME_TYPES, new String[]{"application/json"}); + importProjectLauncher.launch(intent); + } + /* export2 java */ + + private void menuExport2Java() { + dialog = new MaterialAlertDialogBuilder(this) + .setTitle("Generating..") + .setMessage("Please wait code is being generating!") + .setView(new ProgressBar(this)) + .show(); + dialog.setCancelable(false); + dialog.setCanceledOnTouchOutside(false); + new Handler().postDelayed(() -> { + if (mProject.export2Java(getApplicationContext())) { + dialog.dismiss(); + Toast.makeText(this, "Generated! See the files in the app folder in your storage.", Toast.LENGTH_LONG).show(); + } else dialog.dismiss(); + }, 2000); } private void menuCreateCustomType() { - final EditText editText=new EditText(this); - final Context context=getApplicationContext(); - AlertDialog.Builder adb=new AlertDialog.Builder(this); - adb.setTitle("Create custom type") + final EditText editText = new EditText(this); + final Context context = getApplicationContext(); + dialog = new MaterialAlertDialogBuilder(this) + .setTitle("Create custom type") .setMessage("Enter custom type name :") .setView(editText) - .setNegativeButton("CANCEL", new DialogInterface.OnClickListener() { - @Override - public void onClick(DialogInterface dialogInterface, int i) { - - } - }) - .setPositiveButton("OK", new DialogInterface.OnClickListener() { - @Override - public void onClick(DialogInterface dialogInterface, int i) { - String typeName=editText.getText().toString(); - if (typeName.equals("")) - Toast.makeText(context,"Failed : name cannot be blank",Toast.LENGTH_SHORT).show(); - else if (UmlType.containsUmlTypeNamed(typeName)) - Toast.makeText(context,"Failed : this name is already used",Toast.LENGTH_SHORT).show(); - else{ - UmlType.createUmlType(typeName, UmlType.TypeLevel.CUSTOM); - Toast.makeText(context,"Custom type created",Toast.LENGTH_SHORT).show(); - } + .setNegativeButton("Cancel", (d, i) -> dialog.dismiss()) + .setPositiveButton("Ok", (d, i) -> { + String typeName = editText.getText().toString(); + if (typeName.equals("")) + Toast.makeText(context, "Failed : name cannot be blank", Toast.LENGTH_SHORT).show(); + else if (UmlType.containsUmlTypeNamed(typeName)) + Toast.makeText(context, "Failed : this name is already used", Toast.LENGTH_SHORT).show(); + else { + UmlType.createUmlType(typeName, UmlType.TypeLevel.CUSTOM); + Toast.makeText(context, "Custom type created", Toast.LENGTH_SHORT).show(); + dialog.dismiss(); } }) - .create() .show(); } private void menuDeleteCustomTypes() { - final ListView listView=new ListView(this); - List listArray=new ArrayList<>(); - for (UmlType t:UmlType.getUmlTypes()) + final ListView listView = new ListView(this); + List listArray = new ArrayList<>(); + for (UmlType t : UmlType.getUmlTypes()) if (t.isCustomUmlType()) listArray.add(t.getName()); - Collections.sort(listArray,new TypeNameComparator()); - ArrayAdapter adapter=new ArrayAdapter<>(this, android.R.layout.simple_list_item_multiple_choice,listArray); + Collections.sort(listArray, new TypeNameComparator()); + ArrayAdapter adapter = new ArrayAdapter<>(this, android.R.layout.simple_list_item_multiple_choice, listArray); listView.setChoiceMode(AbsListView.CHOICE_MODE_MULTIPLE); listView.setAdapter(adapter); - AlertDialog.Builder adb=new AlertDialog.Builder(this); - adb.setTitle("Delete custom types") - .setMessage("Check custom types to delete") + dialog = new MaterialAlertDialogBuilder(this) + .setTitle("Delete custom types") + .setMessage("Check custom types to delete\nCustom Types: " + listArray.size() + "\n") .setView(listView) - .setNegativeButton("CANCEL", new DialogInterface.OnClickListener() { - @Override - public void onClick(DialogInterface dialogInterface, int i) { - - } - }) - .setPositiveButton("OK", new DialogInterface.OnClickListener() { - @Override - public void onClick(DialogInterface dialogInterface, int i) { - SparseBooleanArray checkMapping=listView.getCheckedItemPositions(); - UmlType t; - for (int j = 0; j < checkMapping.size(); j++) { - if (checkMapping.valueAt(j)) { - t=UmlType.valueOf(listView.getItemAtPosition(checkMapping.keyAt(j)).toString(),UmlType.getUmlTypes()); - UmlType.removeUmlType(t); - mProject.removeParametersOfType(t); - mProject.removeMethodsOfType(t); - mProject.removeAttributesOfType(t); - mGraphView.invalidate(); - } + .setNegativeButton("CANCEL", (d, i) -> dialog.dismiss()) + .setPositiveButton("OK", (d, i) -> { + SparseBooleanArray checkMapping = listView.getCheckedItemPositions(); + UmlType t; + for (int j = 0; j < checkMapping.size(); j++) { + if (checkMapping.valueAt(j)) { + t = UmlType.valueOf(listView.getItemAtPosition(checkMapping.keyAt(j)).toString(), UmlType.getUmlTypes()); + UmlType.removeUmlType(t); + mProject.removeParametersOfType(t); + mProject.removeMethodsOfType(t); + mProject.removeAttributesOfType(t); + mGraphView.invalidate(); + dialog.dismiss(); } } }) - .create() .show(); } private void menuExportCustomTypes() { - Intent intent=new Intent(Intent.ACTION_CREATE_DOCUMENT); + Intent intent = new Intent(Intent.ACTION_CREATE_DOCUMENT); intent.setType("text/*"); - startActivityForResult(intent,INTENT_CREATE_DOCUMENT_EXPORT_CUSTOM_TYPES); + exportCustomTypeLauncher.launch(intent); } private void menuImportCustomTypes() { - Intent intent=new Intent(Intent.ACTION_OPEN_DOCUMENT); + Intent intent = new Intent(Intent.ACTION_OPEN_DOCUMENT); intent.setType("*/*"); - startActivityForResult(intent,INTENT_OPEN_DOCUMENT_IMPORT_CUSTOM_TYPES); + importCustomTypeLauncher.launch(intent); } private void menuHelp() { - AlertDialog.Builder adb=new AlertDialog.Builder(this); - adb.setTitle("Help") - .setMessage(Html.fromHtml(IOUtils.readRawHtmlFile(this,R.raw.help_html))) - .setPositiveButton("OK", new DialogInterface.OnClickListener() { - @Override - public void onClick(DialogInterface dialog, int which) { - - } + new MaterialAlertDialogBuilder(this) + .setTitle("Help") + .setMessage(Html.fromHtml(IOUtils.readRawHtmlFile(this, R.raw.help_html))) + .setPositiveButton("OK", (dialog, which) -> { + dialog.dismiss(); }) - .create() .show(); } -// ********************************************************************************************** + // ********************************************************************************************** // Intents // ********************************************************************************************** - - @Override - protected void onActivityResult(int requestCode, int resultCode, @Nullable Intent data) { - - if (requestCode == INTENT_CREATE_DOCUMENT_EXPORT_PROJECT && resultCode == RESULT_OK) { - Uri fileNameUri=data.getData(); - mProject.exportProject(this,fileNameUri); - } else if (requestCode == INTENT_OPEN_DOCUMENT_IMPORT_PROJECT && resultCode == RESULT_OK) { - Uri fileNameUri=data.getData(); - UmlType.clearProjectUmlTypes(); - mProject=UmlProject.importProject(this,fileNameUri); - mGraphView.setUmlProject(mProject); - } else if (requestCode == INTENT_CREATE_DOCUMENT_EXPORT_CUSTOM_TYPES && resultCode == RESULT_OK) { - Uri fileNameUri=data.getData(); - UmlType.exportCustomUmlTypes(this,fileNameUri); - } else if (requestCode == INTENT_OPEN_DOCUMENT_IMPORT_CUSTOM_TYPES && resultCode == RESULT_OK) { - Uri fileNameUri=data.getData(); - UmlType.importCustomUmlTypes(this,fileNameUri); - } - super.onActivityResult(requestCode, resultCode, data); - } + ActivityResultLauncher exportProjectLauncher = registerForActivityResult( + new ActivityResultContracts.StartActivityForResult(), + result -> { + if (result.getResultCode() == RESULT_OK) { + Intent data = result.getData(); + assert data != null; + Uri fileNameUri = data.getData(); + mProject.exportProject(this, fileNameUri); + } + } + ), + importProjectLauncher = registerForActivityResult( + new ActivityResultContracts.StartActivityForResult(), + result -> { + if (result.getResultCode() == RESULT_OK) { + Intent data = result.getData(); + assert data != null; + Uri fileNameUri = data.getData(); + UmlType.clearProjectUmlTypes(); + mProject = UmlProject.importProject(this, fileNameUri); + mMenuHeaderProjectNameText.setText(mProject.getName()); + mGraphView.setUmlProject(mProject); + } + } + ), + exportCustomTypeLauncher = registerForActivityResult( + new ActivityResultContracts.StartActivityForResult(), + result -> { + if (result.getResultCode() == RESULT_OK) { + Intent data = result.getData(); + assert data != null; + Uri fileNameUri = data.getData(); + UmlType.exportCustomUmlTypes(this, fileNameUri); + } + } + ), + importCustomTypeLauncher = registerForActivityResult( + new ActivityResultContracts.StartActivityForResult(), + result -> { + if (result.getResultCode() == RESULT_OK) { + Intent data = result.getData(); + assert data != null; + Uri fileNameUri = data.getData(); + UmlType.importCustomUmlTypes(this, fileNameUri); + } + } + ), + exportPDFLauncher = registerForActivityResult( + new ActivityResultContracts.StartActivityForResult(), + result -> { + if (result.getResultCode() == RESULT_OK) { + Intent data = result.getData(); + assert data != null; + Uri fileNameUri = data.getData(); + mProject.exportProjectPDF(this, this.mGraphView, fileNameUri); + Toast.makeText(getApplicationContext(), "PDF exported!", Toast.LENGTH_SHORT).show(); + } + } + ),storagePermissionLauncher = registerForActivityResult(new ActivityResultContracts.StartActivityForResult() + ,result ->{ + }) ; @Override public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) { super.onRequestPermissionsResult(requestCode, permissions, grantResults); - if (requestCode == REQUEST_PERMISSION && grantResults[WRITE_EXTERNAL_STORAGE_INDEX]==PackageManager.PERMISSION_GRANTED) - sWriteExternalStoragePermission =true; - else - sWriteExternalStoragePermission =false; - - if (requestCode == REQUEST_PERMISSION && grantResults[READ_EXTERNAL_STORAGE_INDEX]==PackageManager.PERMISSION_GRANTED) - sReadExternalStoragePermission =true; - else - sReadExternalStoragePermission =false; + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M && Build.VERSION.SDK_INT <= Build.VERSION_CODES.S_V2) { + sWriteExternalStoragePermission = requestCode == REQUEST_PERMISSION && grantResults[WRITE_EXTERNAL_STORAGE_INDEX] == PackageManager.PERMISSION_GRANTED; + sReadExternalStoragePermission = requestCode == REQUEST_PERMISSION && grantResults[READ_EXTERNAL_STORAGE_INDEX] == PackageManager.PERMISSION_GRANTED; + } else + sManageExternalStoragePermission = requestCode == REQUEST_PERMISSION && grantResults[MANAGE_EXTERNAL_STORAGE_INDEX] == PackageManager.PERMISSION_GRANTED; } // ********************************************************************************************** // Project management methods // ********************************************************************************************** - private void saveAs(String projectName) { - mProject.setName(projectName); + private void renameProject(String oldName, String newName) { + mProject.setName(newName); + mProject.rename(getApplicationContext(), oldName); + } + + private void saveAs() { updateNavigationView(); mProject.save(getApplicationContext()); + Toast.makeText(getApplicationContext(), "Project saved!", Toast.LENGTH_SHORT).show(); } // ********************************************************************************************** @@ -783,15 +827,26 @@ private void saveAs(String projectName) { @RequiresApi(api = Build.VERSION_CODES.M) private void checkPermissions() { - if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) { + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M && Build.VERSION.SDK_INT <= Build.VERSION_CODES.R) { - String[] permissionString={Manifest.permission.WRITE_EXTERNAL_STORAGE,Manifest.permission.READ_EXTERNAL_STORAGE}; + String[] permissionString = {Manifest.permission.WRITE_EXTERNAL_STORAGE, Manifest.permission.READ_EXTERNAL_STORAGE}; - if (checkSelfPermission(Manifest.permission.WRITE_EXTERNAL_STORAGE)!= PackageManager.PERMISSION_GRANTED - || checkSelfPermission(Manifest.permission.READ_EXTERNAL_STORAGE)!=PackageManager.PERMISSION_GRANTED) + if (checkSelfPermission(Manifest.permission.WRITE_EXTERNAL_STORAGE) != PackageManager.PERMISSION_GRANTED + || checkSelfPermission(Manifest.permission.READ_EXTERNAL_STORAGE) != PackageManager.PERMISSION_GRANTED) requestPermissions(permissionString, REQUEST_PERMISSION); + } else { + if (!Environment.isExternalStorageManager()){ + Intent intent = new Intent(ACTION_MANAGE_APP_ALL_FILES_ACCESS_PERMISSION, Uri.parse("package:" + BuildConfig.APPLICATION_ID)); + storagePermissionLauncher.launch(intent); + } + + } } + public static void hideToolBar(boolean is_locate) { + staticToolbar.setVisibility(is_locate ? View.GONE : View.VISIBLE); + } + } diff --git a/app/src/main/java/com/nathaniel/motus/umlclasseditor/model/UmlClass.java b/app/src/main/java/com/nathaniel/motus/umlclasseditor/model/UmlClass.java index 9d64f4c..3b44356 100644 --- a/app/src/main/java/com/nathaniel/motus/umlclasseditor/model/UmlClass.java +++ b/app/src/main/java/com/nathaniel/motus/umlclasseditor/model/UmlClass.java @@ -1,5 +1,7 @@ package com.nathaniel.motus.umlclasseditor.model; +import android.graphics.Paint; + import org.json.JSONArray; import org.json.JSONException; import org.json.JSONObject; @@ -8,9 +10,9 @@ public class UmlClass extends UmlType { - public enum UmlClassType{JAVA_CLASS,ABSTRACT_CLASS,INTERFACE,ENUM} + public enum UmlClassType {JAVA_CLASS, ABSTRACT_CLASS, INTERFACE, ENUM} - private UmlClassType mUmlClassType=UmlClassType.JAVA_CLASS; + private UmlClassType mUmlClassType = UmlClassType.JAVA_CLASS; private ArrayList mAttributes; private int mUmlClassAttributeCount; private ArrayList mMethods; @@ -24,45 +26,48 @@ public enum UmlClassType{JAVA_CLASS,ABSTRACT_CLASS,INTERFACE,ENUM} private float mUmlClassNormalWidth; private float mUmlClassNormalHeight; - private static final String JSON_CLASS_NAME="ClassName"; - private static final String JSON_CLASS_INDEX="ClassIndex"; - private static final String JSON_CLASS_CLASS_TYPE="ClassClassType"; - private static final String JSON_CLASS_ATTRIBUTES="ClassAttributes"; - private static final String JSON_CLASS_METHODS="ClassMethods"; - private static final String JSON_CLASS_VALUES="ClassValues"; - private static final String JSON_CLASS_NORMAL_XPOS="ClassNormalXPos"; - private static final String JSON_CLASS_NORMAL_YPOS="ClassNormalYPos"; - private static final String JSON_CLASS_ATTRIBUTE_COUNT ="ClassAttributeCount"; - private static final String JSON_CLASS_METHOD_COUNT ="ClassMethodCount"; - private static final String JSON_CLASS_VALUE_COUNT ="ClassValueCount"; + private Paint mUmlClassHeaderPaint; + private int colorPaint; + + private static final String JSON_CLASS_NAME = "ClassName"; + private static final String JSON_CLASS_INDEX = "ClassIndex"; + private static final String JSON_CLASS_CLASS_TYPE = "ClassClassType"; + private static final String JSON_CLASS_ATTRIBUTES = "ClassAttributes"; + private static final String JSON_CLASS_METHODS = "ClassMethods"; + private static final String JSON_CLASS_VALUES = "ClassValues"; + private static final String JSON_CLASS_NORMAL_XPOS = "ClassNormalXPos"; + private static final String JSON_CLASS_NORMAL_YPOS = "ClassNormalYPos"; + private static final String JSON_CLASS_ATTRIBUTE_COUNT = "ClassAttributeCount"; + private static final String JSON_CLASS_METHOD_COUNT = "ClassMethodCount"; + private static final String JSON_CLASS_VALUE_COUNT = "ClassValueCount"; // ********************************************************************************************** // Constructors // ********************************************************************************************** public UmlClass(int classOrder) { - mAttributes=new ArrayList<>(); - mMethods=new ArrayList<>(); - mEnumValues=new ArrayList<>(); - mUmlClassAttributeCount=0; - mUmlClassMethodCount=0; - mValueCount=0; + mAttributes = new ArrayList<>(); + mMethods = new ArrayList<>(); + mEnumValues = new ArrayList<>(); + mUmlClassAttributeCount = 0; + mUmlClassMethodCount = 0; + mValueCount = 0; mClassOrder = classOrder; } public UmlClass(String name) { - this(name,UmlClassType.JAVA_CLASS); + this(name, UmlClassType.JAVA_CLASS); } public UmlClass(String name, UmlClassType umlClassType) { - super(name,TypeLevel.PROJECT); + super(name, TypeLevel.PROJECT); mUmlClassType = umlClassType; mAttributes = new ArrayList<>(); - mUmlClassAttributeCount =0; - mMethods =new ArrayList<>(); - mUmlClassMethodCount =0; - mEnumValues =new ArrayList<>(); - mValueCount =0; + mUmlClassAttributeCount = 0; + mMethods = new ArrayList<>(); + mUmlClassMethodCount = 0; + mEnumValues = new ArrayList<>(); + mValueCount = 0; } public UmlClass(String name, int classOrder, UmlClassType umlClassType, @@ -70,31 +75,32 @@ public UmlClass(String name, int classOrder, UmlClassType umlClassType, ArrayList methods, int methodCount, ArrayList values, int valueCount, float umlClassNormalXPos, float umlClassNormalYPos) { - super(name,TypeLevel.PROJECT); + super(name, TypeLevel.PROJECT); mClassOrder = classOrder; mUmlClassType = umlClassType; mAttributes = attributes; - mUmlClassAttributeCount =attributeCount; + mUmlClassAttributeCount = attributeCount; mMethods = methods; - mUmlClassMethodCount =methodCount; + mUmlClassMethodCount = methodCount; mEnumValues = values; - mValueCount =valueCount; + mValueCount = valueCount; mUmlClassNormalXPos = umlClassNormalXPos; mUmlClassNormalYPos = umlClassNormalYPos; } + public UmlClass(String name, UmlClassType umlClassType, ArrayList attributes, ArrayList methods, ArrayList values, float umlClassNormalXPos, float umlClassNormalYPos) { - super(name,TypeLevel.PROJECT); + super(name, TypeLevel.PROJECT); mUmlClassType = umlClassType; mAttributes = attributes; - mUmlClassAttributeCount =0; + mUmlClassAttributeCount = 0; mMethods = methods; - mUmlClassMethodCount =0; + mUmlClassMethodCount = 0; mEnumValues = values; - mValueCount =0; + mValueCount = 0; mUmlClassNormalXPos = umlClassNormalXPos; mUmlClassNormalYPos = umlClassNormalYPos; } @@ -157,11 +163,11 @@ public ArrayList getValues() { } public float getNormalRightEnd() { - return mUmlClassNormalXPos+mUmlClassNormalWidth; + return mUmlClassNormalXPos + mUmlClassNormalWidth; } public float getNormalBottomEnd() { - return mUmlClassNormalYPos+mUmlClassNormalHeight; + return mUmlClassNormalYPos + mUmlClassNormalHeight; } public void setAttributes(ArrayList attributes) { @@ -219,25 +225,25 @@ public void setClassOrder(int classOrder) { } public UmlClassAttribute findAttributeByOrder(int attributeOrder) { - for (UmlClassAttribute a:mAttributes) - if (a.getAttributeOrder()==attributeOrder) return a; + for (UmlClassAttribute a : mAttributes) + if (a.getAttributeOrder() == attributeOrder) return a; return null; } public UmlClassMethod findMethodByOrder(int methodOrder) { - for (UmlClassMethod m:mMethods) - if (m.getMethodOrder()==methodOrder) return m; - return null; + for (UmlClassMethod m : mMethods) + if (m.getMethodOrder() == methodOrder) return m; + return null; } public UmlEnumValue findValueByOrder(int valueOrder) { - for (UmlEnumValue v:mEnumValues) - if (v.getValueOrder()==valueOrder) return v; - return null; + for (UmlEnumValue v : mEnumValues) + if (v.getValueOrder() == valueOrder) return v; + return null; } public UmlClassAttribute getAttribute(String attributeName) { - for (UmlClassAttribute a:mAttributes) + for (UmlClassAttribute a : mAttributes) if (a.getName().equals(attributeName)) return a; return null; @@ -291,62 +297,62 @@ public void incrementValueCount() { // ********************************************************************************************** public boolean containsPoint(float absoluteX, float absoluteY) { - return (absoluteX<=mUmlClassNormalXPos+mUmlClassNormalWidth && + return (absoluteX <= mUmlClassNormalXPos + mUmlClassNormalWidth && absoluteX >= mUmlClassNormalXPos && - absoluteY<=mUmlClassNormalYPos+mUmlClassNormalHeight && - absoluteY>=mUmlClassNormalYPos); + absoluteY <= mUmlClassNormalYPos + mUmlClassNormalHeight && + absoluteY >= mUmlClassNormalYPos); } public boolean isSouthOf(UmlClass umlClass) { //is this in South quarter of umlClass ? - return (this.getUmlClassNormalYPos()>=umlClass.getNormalBottomEnd() && - this.getNormalRightEnd()>=umlClass.getUmlClassNormalXPos()-this.getUmlClassNormalYPos()+umlClass.getNormalBottomEnd() && - this.getUmlClassNormalXPos()<=umlClass.getNormalRightEnd()+this.getUmlClassNormalYPos()-umlClass.getNormalBottomEnd()); + return (this.getUmlClassNormalYPos() >= umlClass.getNormalBottomEnd() && + this.getNormalRightEnd() >= umlClass.getUmlClassNormalXPos() - this.getUmlClassNormalYPos() + umlClass.getNormalBottomEnd() && + this.getUmlClassNormalXPos() <= umlClass.getNormalRightEnd() + this.getUmlClassNormalYPos() - umlClass.getNormalBottomEnd()); } public boolean isNorthOf(UmlClass umlClass) { //is this in North quarter of umlClass ? - return (this.getNormalBottomEnd()<=umlClass.getUmlClassNormalYPos() && - this.getNormalRightEnd()>=umlClass.getUmlClassNormalXPos()-umlClass.getUmlClassNormalYPos()+this.getNormalBottomEnd() && - this.getUmlClassNormalXPos()<=umlClass.getNormalRightEnd()+umlClass.getUmlClassNormalYPos()-this.getNormalBottomEnd()); + return (this.getNormalBottomEnd() <= umlClass.getUmlClassNormalYPos() && + this.getNormalRightEnd() >= umlClass.getUmlClassNormalXPos() - umlClass.getUmlClassNormalYPos() + this.getNormalBottomEnd() && + this.getUmlClassNormalXPos() <= umlClass.getNormalRightEnd() + umlClass.getUmlClassNormalYPos() - this.getNormalBottomEnd()); } public boolean isWestOf(UmlClass umlClass) { //is this in West quarter of umlClass ? - return (this.getNormalRightEnd()<=umlClass.getUmlClassNormalXPos() && - this.getNormalBottomEnd()>=umlClass.getUmlClassNormalYPos()-umlClass.getUmlClassNormalXPos()+this.getNormalRightEnd() && - this.getUmlClassNormalYPos()<=umlClass.getNormalBottomEnd()+umlClass.getUmlClassNormalXPos()-this.getNormalRightEnd()); + return (this.getNormalRightEnd() <= umlClass.getUmlClassNormalXPos() && + this.getNormalBottomEnd() >= umlClass.getUmlClassNormalYPos() - umlClass.getUmlClassNormalXPos() + this.getNormalRightEnd() && + this.getUmlClassNormalYPos() <= umlClass.getNormalBottomEnd() + umlClass.getUmlClassNormalXPos() - this.getNormalRightEnd()); } public boolean isEastOf(UmlClass umlClass) { //is this in East Quarter of umlClass ? - return (this.getUmlClassNormalXPos()>=umlClass.getNormalRightEnd() && - this.getNormalBottomEnd()>=umlClass.getUmlClassNormalYPos()-this.getUmlClassNormalXPos()+umlClass.getNormalRightEnd() && - this.getUmlClassNormalYPos()<=umlClass.getNormalBottomEnd()+this.getUmlClassNormalXPos()-umlClass.getNormalRightEnd()); + return (this.getUmlClassNormalXPos() >= umlClass.getNormalRightEnd() && + this.getNormalBottomEnd() >= umlClass.getUmlClassNormalYPos() - this.getUmlClassNormalXPos() + umlClass.getNormalRightEnd() && + this.getUmlClassNormalYPos() <= umlClass.getNormalBottomEnd() + this.getUmlClassNormalXPos() - umlClass.getNormalRightEnd()); } public boolean isInvolvedInRelation(UmlRelation umlRelation) { - return (this==umlRelation.getRelationOriginClass()||this==umlRelation.getRelationEndClass()); + return (this == umlRelation.getRelationOriginClass() || this == umlRelation.getRelationEndClass()); } public boolean alreadyExists(UmlProject inProject) { //check whether class name already exists - for (UmlClass c:inProject.getUmlClasses()) + for (UmlClass c : inProject.getUmlClasses()) if (this.getName().equals(c.getName())) return true; return false; } public boolean containsAttributeNamed(String attributeName) { - for (UmlClassAttribute a:mAttributes) - if (a.getName()!=null && a.getName().equals(attributeName)) + for (UmlClassAttribute a : mAttributes) + if (a.getName() != null && a.getName().equals(attributeName)) return true; return false; } public boolean containsEquivalentMethodTo(UmlClassMethod method) { - for (UmlClassMethod m:mMethods) + for (UmlClassMethod m : mMethods) if (m.isEquivalentTo(method)) return true; return false; @@ -357,7 +363,7 @@ public boolean containsEquivalentMethodTo(UmlClassMethod method) { // ********************************************************************************************** public JSONObject toJSONObject() { - JSONObject jsonObject =new JSONObject(); + JSONObject jsonObject = new JSONObject(); try { jsonObject.put(JSON_CLASS_NAME, this.getName().toString()); @@ -394,7 +400,7 @@ public static void populateUmlClassFromJSONObject(JSONObject jsonObject, UmlProj //read a class JSONObject and populate the already created class try { - UmlClass umlClass=project.getUmlClass(jsonObject.getString(JSON_CLASS_NAME)); + UmlClass umlClass = project.getUmlClass(jsonObject.getString(JSON_CLASS_NAME)); umlClass.setClassOrder(jsonObject.getInt(JSON_CLASS_INDEX)); umlClass.setUmlClassType(UmlClassType.valueOf(jsonObject.getString(JSON_CLASS_CLASS_TYPE))); @@ -415,14 +421,14 @@ public static void populateUmlClassFromJSONObject(JSONObject jsonObject, UmlProj private JSONArray getAttributesToJSONArray() { JSONArray jsonArray = new JSONArray(); - for (UmlClassAttribute a: mAttributes) jsonArray.put(a.toJSONObject()); + for (UmlClassAttribute a : mAttributes) jsonArray.put(a.toJSONObject()); return jsonArray; } private static ArrayList getAttributesFromJSONArray(JSONArray jsonArray) { ArrayList umlClassAttributes = new ArrayList<>(); - JSONObject jsonAttribute=(JSONObject) jsonArray.remove(0); + JSONObject jsonAttribute = (JSONObject) jsonArray.remove(0); while (jsonAttribute != null) { umlClassAttributes.add(UmlClassAttribute.fromJSONObject(jsonAttribute)); jsonAttribute = (JSONObject) jsonArray.remove(0); @@ -431,40 +437,54 @@ private static ArrayList getAttributesFromJSONArray(JSONArray } private JSONArray getMethodsToJSONArray() { - JSONArray jsonArray=new JSONArray(); + JSONArray jsonArray = new JSONArray(); - for (UmlClassMethod m: mMethods) jsonArray.put(m.toJSONObject()); + for (UmlClassMethod m : mMethods) jsonArray.put(m.toJSONObject()); return jsonArray; } private static ArrayList getMethodsFromJSONArray(JSONArray jsonArray) { ArrayList umlClassMethods = new ArrayList<>(); - JSONObject jsonMethod=(JSONObject)jsonArray.remove(0); + JSONObject jsonMethod = (JSONObject) jsonArray.remove(0); while (jsonMethod != null) { umlClassMethods.add(UmlClassMethod.fromJSONObject(jsonMethod)); - jsonMethod=(JSONObject)jsonArray.remove(0); + jsonMethod = (JSONObject) jsonArray.remove(0); } return umlClassMethods; } private JSONArray getValuesToJSONArray() { - JSONArray jsonArray=new JSONArray(); + JSONArray jsonArray = new JSONArray(); - for (UmlEnumValue v: mEnumValues) jsonArray.put(v.toJSONObject()); + for (UmlEnumValue v : mEnumValues) jsonArray.put(v.toJSONObject()); return jsonArray; } private static ArrayList getValuesFromJSONArray(JSONArray jsonArray) { ArrayList values = new ArrayList<>(); - JSONObject jsonValue = (JSONObject)jsonArray.remove(0); + JSONObject jsonValue = (JSONObject) jsonArray.remove(0); while (jsonValue != null) { values.add(UmlEnumValue.fromJSONObject(jsonValue)); - jsonValue=(JSONObject) jsonArray.remove(0); + jsonValue = (JSONObject) jsonArray.remove(0); } return values; } + public Paint getmUmlClassHeaderPaint() { + return mUmlClassHeaderPaint; + } + + public void setmUmlClassHeaderPaint(Paint mUmlClassHeaderPaint) { + this.mUmlClassHeaderPaint = mUmlClassHeaderPaint; + } + + public int getColorPaint() { + return colorPaint; + } + public void setColorPaint(int colorPaint) { + this.colorPaint = colorPaint; + } } diff --git a/app/src/main/java/com/nathaniel/motus/umlclasseditor/model/UmlClassAttribute.java b/app/src/main/java/com/nathaniel/motus/umlclasseditor/model/UmlClassAttribute.java index 846aeba..9542636 100644 --- a/app/src/main/java/com/nathaniel/motus/umlclasseditor/model/UmlClassAttribute.java +++ b/app/src/main/java/com/nathaniel/motus/umlclasseditor/model/UmlClassAttribute.java @@ -124,7 +124,7 @@ public String getAttributeCompleteString() { switch (mTypeMultiplicity) { case COLLECTION: - completeString=completeString+mName+" : <"+mUmlType.getName()+">"; + completeString=completeString+mName+" : List<"+mUmlType.getName()+">"; break; case ARRAY: completeString=completeString+mName+" : ["+mUmlType.getName()+"]^"+ mArrayDimension; diff --git a/app/src/main/java/com/nathaniel/motus/umlclasseditor/model/UmlClassMethod.java b/app/src/main/java/com/nathaniel/motus/umlclasseditor/model/UmlClassMethod.java index e7315c1..cd5510e 100644 --- a/app/src/main/java/com/nathaniel/motus/umlclasseditor/model/UmlClassMethod.java +++ b/app/src/main/java/com/nathaniel/motus/umlclasseditor/model/UmlClassMethod.java @@ -6,27 +6,27 @@ import java.util.ArrayList; -public class UmlClassMethod implements AdapterItem{ +public class UmlClassMethod implements AdapterItem { private String mName; private int mMethodOrder; - private Visibility mVisibility=Visibility.PRIVATE; - private boolean mStatic =false; + private Visibility mVisibility = Visibility.PRIVATE; + private boolean mStatic = false; private UmlType mUmlType; - private TypeMultiplicity mTypeMultiplicity=TypeMultiplicity.SINGLE; - private int mArrayDimension =1; + private TypeMultiplicity mTypeMultiplicity = TypeMultiplicity.SINGLE; + private int mArrayDimension = 1; private ArrayList mParameters; private int mParameterCount; - public static final String JSON_CLASS_METHOD_NAME="ClassMethodName"; - public static final String JSON_CLASS_METHOD_VISIBILITY="ClassMethodVisibility"; - public static final String JSON_CLASS_METHOD_STATIC="ClassMethodStatic"; - public static final String JSON_CLASS_METHOD_TYPE="ClassMethodType"; - public static final String JSON_CLASS_METHOD_TYPE_MULTIPLICITY="ClassMethodTypeMultiplicity"; - public static final String JSON_CLASS_METHOD_ARRAY_DIMENSION="ClassMethodArrayDimension"; - public static final String JSON_CLASS_METHOD_PARAMETERS="ClassMethodParameters"; - public static final String JSON_CLASS_METHOD_PARAMETER_COUNT="ClassMethodParameterCount"; - public static final String JSON_CLASS_METHOD_INDEX="ClassMethodIndex"; + public static final String JSON_CLASS_METHOD_NAME = "ClassMethodName"; + public static final String JSON_CLASS_METHOD_VISIBILITY = "ClassMethodVisibility"; + public static final String JSON_CLASS_METHOD_STATIC = "ClassMethodStatic"; + public static final String JSON_CLASS_METHOD_TYPE = "ClassMethodType"; + public static final String JSON_CLASS_METHOD_TYPE_MULTIPLICITY = "ClassMethodTypeMultiplicity"; + public static final String JSON_CLASS_METHOD_ARRAY_DIMENSION = "ClassMethodArrayDimension"; + public static final String JSON_CLASS_METHOD_PARAMETERS = "ClassMethodParameters"; + public static final String JSON_CLASS_METHOD_PARAMETER_COUNT = "ClassMethodParameterCount"; + public static final String JSON_CLASS_METHOD_INDEX = "ClassMethodIndex"; // ********************************************************************************************** // Constructors @@ -40,8 +40,8 @@ public UmlClassMethod(String name, int methodOrder, Visibility visibility, boole mUmlType = umlType; mTypeMultiplicity = typeMultiplicity; mArrayDimension = arrayDimension; - mParameters=new ArrayList<>(); - mParameterCount=0; + mParameters = new ArrayList<>(); + mParameterCount = 0; } public UmlClassMethod(String mName, int methodOrder, Visibility mVisibility, boolean mStatic, UmlType mUmlType, TypeMultiplicity mTypeMultiplicity, int mArrayDimension, ArrayList mParameters, int parameterCount) { @@ -53,13 +53,13 @@ public UmlClassMethod(String mName, int methodOrder, Visibility mVisibility, boo this.mTypeMultiplicity = mTypeMultiplicity; this.mArrayDimension = mArrayDimension; this.mParameters = mParameters; - this.mParameterCount=parameterCount; + this.mParameterCount = parameterCount; } public UmlClassMethod(int methodOrder) { mMethodOrder = methodOrder; - mParameterCount=0; - mParameters=new ArrayList<>(); + mParameterCount = 0; + mParameters = new ArrayList<>(); } // ********************************************************************************************** @@ -137,55 +137,55 @@ public void setParameterCount(int parameterCount) { public String getMethodCompleteString() { //return method name with conventional modifiers - String completeString=new String(); + StringBuilder completeString = new StringBuilder(new String()); switch (mVisibility) { case PUBLIC: - completeString="+"; + completeString = new StringBuilder("+"); break; case PROTECTED: - completeString="~"; + completeString = new StringBuilder("~"); break; default: - completeString="-"; + completeString = new StringBuilder("-"); break; } - completeString=completeString+mName+"("; + completeString.append(mName).append("("); - for (MethodParameter p:mParameters) { - completeString = completeString + p.getName(); - if (mParameters.indexOf(p)!=mParameters.size()-1) - completeString=completeString+", "; + for (MethodParameter p : mParameters) { + completeString.append(p.getName()).append(": ").append(p.getUmlType().mName); + if (mParameters.indexOf(p) != mParameters.size() - 1) + completeString.append(", "); } - completeString=completeString+") : "; + completeString.append(") : "); switch (mTypeMultiplicity) { case COLLECTION: - completeString=completeString+"<"+mUmlType.getName()+">"; + completeString.append("List<").append(mUmlType.getName()).append(">"); break; case ARRAY: - completeString=completeString+"["+mUmlType.getName()+"]^"+mArrayDimension; + completeString.append("[").append(mUmlType.getName()).append("]^").append(mArrayDimension); break; default: - completeString=completeString+mUmlType.getName(); + completeString.append(mUmlType.getName()); } - return completeString; + return completeString.toString(); } public static int indexOf(String methodName, ArrayList methods) { - for (UmlClassMethod m:methods) + for (UmlClassMethod m : methods) if (methodName.equals(m.mName)) return methods.indexOf(m); return -1; } public MethodParameter findParameterByOrder(int parameterOrder) { - for (MethodParameter p:mParameters) - if (p.getParameterOrder()==parameterOrder) return p; - return null; + for (MethodParameter p : mParameters) + if (p.getParameterOrder() == parameterOrder) return p; + return null; } public MethodParameter getParameter(String parameterName) { @@ -212,24 +212,24 @@ public void incrementParameterCount() { mParameterCount++; } -// ********************************************************************************************** + // ********************************************************************************************** // Test methods // ********************************************************************************************** public boolean containsParameterNamed(String parameterName) { - for (MethodParameter p:mParameters) - if (p.getName()!=null && p.getName().equals(parameterName)) + for (MethodParameter p : mParameters) + if (p.getName() != null && p.getName().equals(parameterName)) return true; return false; } public boolean isEquivalentTo(UmlClassMethod method) { - if (this.mMethodOrder==method.mMethodOrder) + if (this.mMethodOrder == method.mMethodOrder) return false; if (!this.mName.equals(method.mName)) return false; - if (this.mUmlType!=method.mUmlType) + if (this.mUmlType != method.mUmlType) return false; - if (this.mParameters.size()!=method.mParameters.size()) + if (this.mParameters.size() != method.mParameters.size()) return false; for (int i = 0; i < this.mParameters.size(); i++) { if (!this.mParameters.get(i).isEquivalentTo(method.mParameters.get(i))) @@ -243,7 +243,7 @@ public boolean isEquivalentTo(UmlClassMethod method) { // ********************************************************************************************** public JSONObject toJSONObject() { - JSONObject jsonObject=new JSONObject(); + JSONObject jsonObject = new JSONObject(); try { jsonObject.put(JSON_CLASS_METHOD_NAME, mName); @@ -254,7 +254,7 @@ public JSONObject toJSONObject() { jsonObject.put(JSON_CLASS_METHOD_TYPE_MULTIPLICITY, mTypeMultiplicity); jsonObject.put(JSON_CLASS_METHOD_ARRAY_DIMENSION, mArrayDimension); jsonObject.put(JSON_CLASS_METHOD_PARAMETERS, getParametersToJSONArray()); - jsonObject.put(JSON_CLASS_METHOD_PARAMETER_COUNT,mParameterCount); + jsonObject.put(JSON_CLASS_METHOD_PARAMETER_COUNT, mParameterCount); return jsonObject; } catch (JSONException jsonException) { return null; @@ -263,7 +263,7 @@ public JSONObject toJSONObject() { public static UmlClassMethod fromJSONObject(JSONObject jsonObject) { try { - if (UmlType.valueOf(jsonObject.getString(JSON_CLASS_METHOD_TYPE),UmlType.getUmlTypes())==null) + if (UmlType.valueOf(jsonObject.getString(JSON_CLASS_METHOD_TYPE), UmlType.getUmlTypes()) == null) UmlType.createUmlType(jsonObject.getString(JSON_CLASS_METHOD_TYPE), UmlType.TypeLevel.CUSTOM); return new UmlClassMethod(jsonObject.getString(JSON_CLASS_METHOD_NAME), @@ -281,19 +281,19 @@ public static UmlClassMethod fromJSONObject(JSONObject jsonObject) { } private JSONArray getParametersToJSONArray() { - JSONArray jsonArray =new JSONArray(); + JSONArray jsonArray = new JSONArray(); for (MethodParameter p : this.mParameters) jsonArray.put(p.toJSONObject()); return jsonArray; } private static ArrayList getParametersFromJSONArray(JSONArray jsonArray) { - ArrayList methodParameters=new ArrayList<>(); + ArrayList methodParameters = new ArrayList<>(); - JSONObject jsonParameter=(JSONObject)(jsonArray.remove(0)); + JSONObject jsonParameter = (JSONObject) (jsonArray.remove(0)); while (jsonParameter != null) { methodParameters.add(MethodParameter.fromJSONObject(jsonParameter)); - jsonParameter=(JSONObject)(jsonArray.remove(0)); + jsonParameter = (JSONObject) (jsonArray.remove(0)); } return methodParameters; } diff --git a/app/src/main/java/com/nathaniel/motus/umlclasseditor/model/UmlProject.java b/app/src/main/java/com/nathaniel/motus/umlclasseditor/model/UmlProject.java index 6b77be9..a5b72b4 100644 --- a/app/src/main/java/com/nathaniel/motus/umlclasseditor/model/UmlProject.java +++ b/app/src/main/java/com/nathaniel/motus/umlclasseditor/model/UmlProject.java @@ -5,6 +5,7 @@ import android.util.Log; import com.nathaniel.motus.umlclasseditor.controller.IOUtils; +import com.nathaniel.motus.umlclasseditor.view.GraphView; import org.json.JSONArray; import org.json.JSONException; @@ -117,7 +118,7 @@ public void setUmlClassCount(int umlClassCount) { public UmlClass findClassByOrder(int classOrder) { for (UmlClass c:mUmlClasses) if (c.getClassOrder()==classOrder) return c; - return null; + return null; } // ********************************************************************************************** @@ -319,6 +320,13 @@ private static ArrayList getRelationsFromJSONArray(JSONArray jsonAr // Save and load project methods // ********************************************************************************************** + public void rename(Context context,String oldName){ + File destination=new File(context.getFilesDir(),PROJECT_DIRECTORY); + File source=new File(destination,oldName); + if(source.exists()) source.delete(); + + save(context); + } public void save(Context context) { File destination=new File(context.getFilesDir(),PROJECT_DIRECTORY); if (!destination.exists()) destination.mkdir(); @@ -339,6 +347,13 @@ public static UmlProject load(Context context, String projectName) { public void exportProject(Context context, Uri toDestination) { IOUtils.saveFileToExternalStorage(context,this.toJSONObject(context).toString(),toDestination); } + public void exportProjectPDF(Context context, GraphView graphView, Uri toDestination) { + IOUtils.savePdfToExternalStorage(context,graphView,toDestination); + } + /* export2java*/ + public boolean export2Java(Context context){ + return IOUtils.export2Java(context,this); + } public static UmlProject importProject(Context context, Uri fromFileUri) { UmlProject umlProject; diff --git a/app/src/main/java/com/nathaniel/motus/umlclasseditor/view/AttributeEditorFragment.java b/app/src/main/java/com/nathaniel/motus/umlclasseditor/view/AttributeEditorFragment.java index 6cf7bd0..0deec40 100644 --- a/app/src/main/java/com/nathaniel/motus/umlclasseditor/view/AttributeEditorFragment.java +++ b/app/src/main/java/com/nathaniel/motus/umlclasseditor/view/AttributeEditorFragment.java @@ -1,9 +1,11 @@ package com.nathaniel.motus.umlclasseditor.view; +import android.annotation.SuppressLint; import android.app.AlertDialog; import android.content.DialogInterface; import android.os.Bundle; +import androidx.annotation.NonNull; import androidx.fragment.app.Fragment; import android.view.LayoutInflater; @@ -19,7 +21,9 @@ import android.widget.TextView; import android.widget.Toast; +import com.google.android.material.dialog.MaterialAlertDialogBuilder; import com.nathaniel.motus.umlclasseditor.R; +import com.nathaniel.motus.umlclasseditor.databinding.FragmentAttributeEditorBinding; import com.nathaniel.motus.umlclasseditor.model.TypeMultiplicity; import com.nathaniel.motus.umlclasseditor.model.TypeNameComparator; import com.nathaniel.motus.umlclasseditor.model.UmlClass; @@ -37,7 +41,7 @@ * create an instance of this fragment. */ public class AttributeEditorFragment extends EditorFragment implements View.OnClickListener, RadioGroup.OnCheckedChangeListener { - + private FragmentAttributeEditorBinding binding; private static final String ATTRIBUTE_ORDER_KEY = "attributeOrder"; private static final String CLASS_ORDER_KEY ="classOrder"; private static final String CLASS_EDITOR_FRAGMENT_TAG_KEY="classEditorFragmentTag"; @@ -46,25 +50,6 @@ public class AttributeEditorFragment extends EditorFragment implements View.OnCl private UmlClassAttribute mUmlClassAttribute; private String mClassEditorFragmentTag; private UmlClass mUmlClass; - - private TextView mEditAttributeText; - private Button mDeleteAttributeButton; - private EditText mAttributeNameEdit; - private RadioButton mPublicRadio; - private RadioButton mProtectedRadio; - private RadioButton mPrivateRadio; - private CheckBox mStaticCheck; - private CheckBox mFinalCheck; - private Spinner mTypeSpinner; - private RadioGroup mMultiplicityRadioGroup; - private RadioButton mSimpleRadio; - private RadioButton mCollectionRadio; - private RadioButton mArrayRadio; - private TextView mDimText; - private EditText mDimEdit; - private Button mOKButton; - private Button mCancelButton; - private static final int TYPE_SPINNER_TAG=310; private static final int OK_BUTTON_TAG=320; private static final int CANCEL_BUTTON_TAG=330; @@ -93,10 +78,11 @@ public static AttributeEditorFragment newInstance(String classEditorFragmentTag, // ********************************************************************************************** @Override - public View onCreateView(LayoutInflater inflater, ViewGroup container, + public View onCreateView(@NonNull LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { // Inflate the layout for this fragment - return inflater.inflate(R.layout.fragment_attribute_editor, container, false); + binding = FragmentAttributeEditorBinding.inflate(inflater,container,false); + return binding.getRoot(); } // ********************************************************************************************** @@ -118,47 +104,19 @@ protected void setOnCreateOrEditDisplay() { @Override protected void configureViews() { - mEditAttributeText=getActivity().findViewById(R.id.edit_attribute_text); - - mDeleteAttributeButton=getActivity().findViewById(R.id.delete_attribute_button); - mDeleteAttributeButton.setTag(DELETE_ATTRIBUTE_BUTTON_TAG); - mDeleteAttributeButton.setOnClickListener(this); - - mAttributeNameEdit=getActivity().findViewById(R.id.attribute_name_input); - - mMultiplicityRadioGroup=getActivity().findViewById(R.id.attribute_multiplicity_radio_group); - mMultiplicityRadioGroup.setOnCheckedChangeListener(this); - - mPublicRadio=getActivity().findViewById(R.id.attribute_public_radio); - - mProtectedRadio=getActivity().findViewById(R.id.attribute_protected_radio); - - mPrivateRadio=getActivity().findViewById(R.id.attribute_private_radio); - - mStaticCheck=getActivity().findViewById(R.id.attribute_static_check); - - mFinalCheck=getActivity().findViewById(R.id.attribute_final_check); - - mTypeSpinner=getActivity().findViewById(R.id.attribute_type_spinner); - mTypeSpinner.setTag(TYPE_SPINNER_TAG); - - mSimpleRadio =getActivity().findViewById(R.id.attribute_simple_radio); - - mCollectionRadio=getActivity().findViewById(R.id.attribute_collection_radio); - - mArrayRadio =getActivity().findViewById(R.id.attribute_array_radio); - - mDimText=getActivity().findViewById(R.id.attribute_dimension_text); - - mDimEdit=getActivity().findViewById(R.id.attribute_dimension_input); - - mOKButton=getActivity().findViewById(R.id.attribute_ok_button); - mOKButton.setTag(OK_BUTTON_TAG); - mOKButton.setOnClickListener(this); - - mCancelButton=getActivity().findViewById(R.id.attribute_cancel_button); - mCancelButton.setTag(CANCEL_BUTTON_TAG); - mCancelButton.setOnClickListener(this); + // delete btn + binding.deleteAttributeButton.setTag(DELETE_ATTRIBUTE_BUTTON_TAG); + binding.deleteAttributeButton.setOnClickListener(this); + // attrib type radio grp + binding.attributeMultiplicityRadioGroup.setOnCheckedChangeListener(this); + // spinner + binding.attributeTypeSpinner.setTag(TYPE_SPINNER_TAG); + // ok btn + binding.attributeOkButton.setTag(OK_BUTTON_TAG); + binding.attributeOkButton.setOnClickListener(this); + // cancel btn + binding.attributeCancelButton.setTag(CANCEL_BUTTON_TAG); + binding.attributeCancelButton.setOnClickListener(this); } @@ -175,50 +133,51 @@ protected void initializeMembers() { } + @SuppressLint("SetTextI18n") @Override protected void initializeFields() { if (mAttributeOrder != -1) { - mAttributeNameEdit.setText(mUmlClassAttribute.getName()); + binding.attributeNameInput.setText(mUmlClassAttribute.getName()); switch (mUmlClassAttribute.getVisibility()) { case PUBLIC: - mPublicRadio.setChecked(true); + binding.attributePublicRadio.setChecked(true); break; case PROTECTED: - mProtectedRadio.setChecked(true); + binding.attributeProtectedRadio.setChecked(true); break; default: - mPrivateRadio.setChecked(true); + binding.attributePrivateRadio.setChecked(true); break; } - mStaticCheck.setChecked(mUmlClassAttribute.isStatic()); - mFinalCheck.setChecked(mUmlClassAttribute.isFinal()); + binding.attributeStaticCheck.setChecked(mUmlClassAttribute.isStatic()); + binding.attributeFinalCheck.setChecked(mUmlClassAttribute.isFinal()); switch (mUmlClassAttribute.getTypeMultiplicity()) { case SINGLE: - mSimpleRadio.setChecked(true); + binding.attributeSimpleRadio.setChecked(true); break; case COLLECTION: - mCollectionRadio.setChecked(true); + binding.attributeCollectionRadio.setChecked(true); break; default: - mArrayRadio.setChecked(true); + binding.attributeArrayRadio.setChecked(true); break; } - mDimEdit.setText(Integer.toString(mUmlClassAttribute.getArrayDimension())); + binding.attributeDimensionInput.setText(Integer.toString(mUmlClassAttribute.getArrayDimension())); if (mUmlClassAttribute.getTypeMultiplicity() == TypeMultiplicity.ARRAY) setOnArrayDisplay(); else setOnSingleDisplay(); } else { - mAttributeNameEdit.setText(""); - mPublicRadio.setChecked(true); - mStaticCheck.setChecked(false); - mFinalCheck.setChecked(false); - mSimpleRadio.setChecked(true); - mDimEdit.setText(""); + binding.attributeNameInput.setText(""); + binding.attributePublicRadio.setChecked(true); + binding.attributeStaticCheck.setChecked(false); + binding.attributeFinalCheck.setChecked(false); + binding.attributeSimpleRadio.setChecked(true); + binding.attributeDimensionInput.setText(""); setOnSingleDisplay(); } populateTypeSpinner(); @@ -231,29 +190,29 @@ private void populateTypeSpinner() { Collections.sort(spinnerArray,new TypeNameComparator()); ArrayAdapter adapter=new ArrayAdapter<>(getContext(),android.R.layout.simple_spinner_item,spinnerArray); adapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item); - mTypeSpinner.setAdapter(adapter); + binding.attributeTypeSpinner.setAdapter(adapter); if (mAttributeOrder !=-1) - mTypeSpinner.setSelection(spinnerArray.indexOf(mUmlClassAttribute.getUmlType().getName())); + binding.attributeTypeSpinner.setSelection(spinnerArray.indexOf(mUmlClassAttribute.getUmlType().getName())); } private void setOnEditDisplay() { - mDeleteAttributeButton.setVisibility(View.VISIBLE); - mEditAttributeText.setText("Edit attribute"); + binding.deleteAttributeButton.setVisibility(View.VISIBLE); + binding.editAttributeText.setText("Edit attribute"); } private void setOnCreateDisplay() { - mDeleteAttributeButton.setVisibility(View.INVISIBLE); - mEditAttributeText.setText("Create attribute"); + binding.deleteAttributeButton.setVisibility(View.INVISIBLE); + binding.editAttributeText.setText("Create attribute"); } private void setOnArrayDisplay() { - mDimText.setVisibility(View.VISIBLE); - mDimEdit.setVisibility(View.VISIBLE); + binding.attributeDimensionText.setVisibility(View.VISIBLE); + binding.attributeDimensionInput.setVisibility(View.VISIBLE); } private void setOnSingleDisplay() { - mDimText.setVisibility(View.INVISIBLE); - mDimEdit.setVisibility(View.INVISIBLE); + binding.attributeDimensionText.setVisibility(View.INVISIBLE); + binding.attributeDimensionInput.setVisibility(View.INVISIBLE); } public void updateAttributeEditorFragment(int attributeOrder, int classOrder) { @@ -344,36 +303,36 @@ private boolean createOrUpdateAttribute() { } private String getAttributeName() { - return mAttributeNameEdit.getText().toString(); + return binding.attributeNameInput.getText().toString(); } private Visibility getVisibility() { - if (mPublicRadio.isChecked()) return Visibility.PUBLIC; - if (mProtectedRadio.isChecked()) return Visibility.PROTECTED; + if (binding.attributePublicRadio.isChecked()) return Visibility.PUBLIC; + if (binding.attributeProtectedRadio.isChecked()) return Visibility.PROTECTED; return Visibility.PRIVATE; } private boolean isStatic() { - return mStaticCheck.isChecked(); + return binding.attributeStaticCheck.isChecked(); } private boolean isFinal() { - return mFinalCheck.isChecked(); + return binding.attributeFinalCheck.isChecked(); } private UmlType getType() { - return UmlType.valueOf(mTypeSpinner.getSelectedItem().toString(),UmlType.getUmlTypes()); + return UmlType.valueOf(binding.attributeTypeSpinner.getSelectedItem().toString(),UmlType.getUmlTypes()); } private TypeMultiplicity getMultiplicity() { - if (mSimpleRadio.isChecked()) return TypeMultiplicity.SINGLE; - if (mCollectionRadio.isChecked()) return TypeMultiplicity.COLLECTION; + if (binding.attributeSimpleRadio.isChecked()) return TypeMultiplicity.SINGLE; + if (binding.attributeCollectionRadio.isChecked()) return TypeMultiplicity.COLLECTION; return TypeMultiplicity.ARRAY; } private int getArrayDimension() { - if (mDimEdit.getText().toString().equals("")) return 0; - return Integer.parseInt(mDimEdit.getText().toString()); + if (binding.attributeDimensionInput.getText().toString().equals("")) return 0; + return Integer.parseInt(binding.attributeDimensionInput.getText().toString()); } // ********************************************************************************************** @@ -382,23 +341,14 @@ private int getArrayDimension() { private void startDeleteAttributeDialog() { final Fragment fragment=this; - AlertDialog.Builder builder=new AlertDialog.Builder(getContext()); - builder.setTitle("Delete attribute") + new MaterialAlertDialogBuilder(requireContext()) + .setTitle("Delete attribute") .setMessage("Are you sure you want to delete this attribute ?") - .setNegativeButton("NO", new DialogInterface.OnClickListener() { - @Override - public void onClick(DialogInterface dialog, int which) { - - } - }) - .setPositiveButton("YES", new DialogInterface.OnClickListener() { - @Override - public void onClick(DialogInterface dialog, int which) { - mUmlClass.getAttributes().remove(mUmlClassAttribute); - mCallback.closeAttributeEditorFragment(fragment); - } - }); - AlertDialog dialog=builder.create(); - dialog.show(); + .setNegativeButton("NO", (d, which) -> d.dismiss()) + .setPositiveButton("YES", (d, which) -> { + mUmlClass.getAttributes().remove(mUmlClassAttribute); + mCallback.closeAttributeEditorFragment(fragment); + }).show(); + } } \ No newline at end of file diff --git a/app/src/main/java/com/nathaniel/motus/umlclasseditor/view/ClassEditorFragment.java b/app/src/main/java/com/nathaniel/motus/umlclasseditor/view/ClassEditorFragment.java index c1f8aaa..ea558b3 100644 --- a/app/src/main/java/com/nathaniel/motus/umlclasseditor/view/ClassEditorFragment.java +++ b/app/src/main/java/com/nathaniel/motus/umlclasseditor/view/ClassEditorFragment.java @@ -17,10 +17,13 @@ import android.widget.TextView; import android.widget.Toast; +import androidx.annotation.NonNull; import androidx.fragment.app.Fragment; +import com.google.android.material.dialog.MaterialAlertDialogBuilder; import com.nathaniel.motus.umlclasseditor.R; import com.nathaniel.motus.umlclasseditor.controller.CustomExpandableListViewAdapter; +import com.nathaniel.motus.umlclasseditor.databinding.FragmentClassEditorBinding; import com.nathaniel.motus.umlclasseditor.model.AdapterItem; import com.nathaniel.motus.umlclasseditor.model.AdapterItemComparator; import com.nathaniel.motus.umlclasseditor.model.AddItemString; @@ -34,24 +37,13 @@ import java.util.Collections; import java.util.HashMap; import java.util.List; +import java.util.Objects; public class ClassEditorFragment extends EditorFragment implements View.OnClickListener , AdapterView.OnItemLongClickListener, RadioGroup.OnCheckedChangeListener, ExpandableListView.OnChildClickListener{ - - private TextView mEditClassText; - private EditText mClassNameEdit; - private Button mDeleteClassButton; - private RadioGroup mClassTypeRadioGroup; - private RadioButton mJavaRadio; - private RadioButton mAbstractRadio; - private RadioButton mInterfaceRadio; - private RadioButton mEnumRadio; - private ExpandableListView mMemberListView; - private Button mOKButton; - private Button mCancelButton; - private LinearLayout mOKCancelLinearLayout; + private FragmentClassEditorBinding binding; private static boolean sIsJavaClass=true; @@ -98,10 +90,11 @@ public static ClassEditorFragment newInstance(float xPos, float yPos,int classOr // ********************************************************************************************** @Override - public View onCreateView(LayoutInflater inflater, ViewGroup container, + public View onCreateView(@NonNull LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { // Inflate the layout for this fragment - return inflater.inflate(R.layout.fragment_class_editor, container, false); + binding = FragmentClassEditorBinding.inflate(inflater,container,false); + return binding.getRoot(); } // ********************************************************************************************** @@ -122,36 +115,25 @@ protected void setOnCreateOrEditDisplay() { @Override protected void configureViews() { - mEditClassText =getActivity().findViewById(R.id.edit_class_text); - - mClassNameEdit=getActivity().findViewById(R.id.class_name_input); - - mDeleteClassButton=getActivity().findViewById(R.id.delete_class_button); - mDeleteClassButton.setTag(DELETE_CLASS_BUTTON_TAG); - mDeleteClassButton.setOnClickListener(this); + // delete btn + binding.deleteClassButton.setTag(DELETE_CLASS_BUTTON_TAG); + binding.deleteClassButton.setOnClickListener(this); - mClassTypeRadioGroup=getActivity().findViewById(R.id.class_type_radio_group); - mClassTypeRadioGroup.setOnCheckedChangeListener(this); + // class type radio group + binding.classTypeRadioGroup.setOnCheckedChangeListener(this); - mJavaRadio=getActivity().findViewById(R.id.class_java_radio); - mAbstractRadio=getActivity().findViewById(R.id.class_abstract_radio); - mInterfaceRadio=getActivity().findViewById(R.id.class_interface_radio); - mEnumRadio=getActivity().findViewById(R.id.class_enum_radio); + // class members - methods & attributes + binding.classMembersList.setTag(MEMBER_LIST_TAG); + binding.classMembersList.setOnChildClickListener(this); + binding.classMembersList.setOnItemLongClickListener(this); - mMemberListView =getActivity().findViewById(R.id.class_members_list); - mMemberListView.setTag(MEMBER_LIST_TAG); - mMemberListView.setOnChildClickListener(this); - mMemberListView.setOnItemLongClickListener(this); + // ok btn + binding.classOkButton.setTag(OK_BUTTON_TAG); + binding.classOkButton.setOnClickListener(this); - mOKButton=getActivity().findViewById(R.id.class_ok_button); - mOKButton.setTag(OK_BUTTON_TAG); - mOKButton.setOnClickListener(this); - - mCancelButton=getActivity().findViewById(R.id.class_cancel_button); - mCancelButton.setTag(CANCEL_BUTTON_TAG); - mCancelButton.setOnClickListener(this); - - mOKCancelLinearLayout=getActivity().findViewById(R.id.class_ok_cancel_linear); + // cancel btn + binding.classCancelButton.setTag(CANCEL_BUTTON_TAG); + binding.classCancelButton.setOnClickListener(this); } @Override @@ -171,25 +153,25 @@ protected void initializeMembers() { protected void initializeFields() { if (mClassOrder != -1) { - mClassNameEdit.setText(mUmlClass.getName()); + binding.classNameInput.setText(mUmlClass.getName()); switch (mUmlClass.getUmlClassType()) { case JAVA_CLASS: - mJavaRadio.setChecked(true); + binding.classJavaRadio.setChecked(true); break; case ABSTRACT_CLASS: - mAbstractRadio.setChecked(true); + binding.classAbstractRadio.setChecked(true); break; case INTERFACE: - mInterfaceRadio.setChecked(true); + binding.classInterfaceRadio.setChecked(true); break; default: - mEnumRadio.setChecked(true); + binding.classEnumRadio.setChecked(true); break; } } else { - mClassNameEdit.setText(""); - mJavaRadio.setChecked(true); + binding.classNameInput.setText(""); + binding.classJavaRadio.setChecked(true); } updateLists(); } @@ -197,10 +179,11 @@ protected void initializeFields() { private void populateMemberListViewForJavaClass() { boolean attributeGroupIsExpanded=false; boolean methodGroupIsExpanded=false; - if (mMemberListView.getExpandableListAdapter() != null) { - if (mMemberListView.isGroupExpanded(0)) + ExpandableListView membersListView = binding.classMembersList; + if (membersListView.getExpandableListAdapter() != null) { + if (membersListView.isGroupExpanded(0)) attributeGroupIsExpanded = true; - if (mMemberListView.isGroupExpanded(1)) + if (membersListView.isGroupExpanded(1)) methodGroupIsExpanded=true; } @@ -224,12 +207,12 @@ private void populateMemberListViewForJavaClass() { hashMap.put(getString(R.string.attributes_string),attributeList); hashMap.put(getString(R.string.methods_string),methodList); CustomExpandableListViewAdapter adapter=new CustomExpandableListViewAdapter(getContext(),title,hashMap); - mMemberListView.setAdapter(adapter); + membersListView.setAdapter(adapter); if (attributeGroupIsExpanded) - mMemberListView.expandGroup(0); + membersListView.expandGroup(0); if (methodGroupIsExpanded) - mMemberListView.expandGroup(1); + membersListView.expandGroup(1); } private void populateMemberListViewForEnum() { @@ -244,7 +227,7 @@ private void populateMemberListViewForEnum() { HashMap> hashMap=new HashMap<>(); hashMap.put(getString(R.string.values_string),valueList); CustomExpandableListViewAdapter adapter=new CustomExpandableListViewAdapter(getContext(),title,hashMap); - mMemberListView.setAdapter(adapter); + binding.classMembersList.setAdapter(adapter); } public void updateLists() { @@ -253,13 +236,13 @@ public void updateLists() { } private void setOnEditDisplay() { - mEditClassText.setText("Edit class"); - mDeleteClassButton.setVisibility(View.VISIBLE); + binding.editClassText.setText("Edit class"); + binding.deleteClassButton.setVisibility(View.VISIBLE); } private void setOnCreateDisplay() { - mEditClassText.setText("Create class"); - mDeleteClassButton.setVisibility(View.INVISIBLE); + binding.editClassText.setText("Create class"); + binding.deleteClassButton.setVisibility(View.GONE); } public void updateClassEditorFragment(float xPos, float yPos, int classOrder) { @@ -270,8 +253,7 @@ public void updateClassEditorFragment(float xPos, float yPos, int classOrder) { initializeFields(); if (mClassOrder ==-1) setOnCreateDisplay(); else setOnEditDisplay(); - if (mClassOrder !=-1 && mUmlClass.getUmlClassType()== UmlClass.UmlClassType.ENUM) sIsJavaClass=false; - else sIsJavaClass=true; + sIsJavaClass= mClassOrder == -1 || mUmlClass.getUmlClassType() != UmlClass.UmlClassType.ENUM; setOnBackPressedCallback(); } @@ -333,8 +315,7 @@ else if ((expandableListView.getExpandableListAdapter().getGroup(groupPos)).equa @Override public void onCheckedChanged(RadioGroup group, int checkedId) { - if (checkedId==R.id.class_enum_radio) sIsJavaClass=false; - else sIsJavaClass=true; + sIsJavaClass= checkedId != R.id.class_enum_radio; updateLists(); } @@ -399,13 +380,13 @@ private boolean createOrUpdateClass() { } private String getClassName() { - return mClassNameEdit.getText().toString(); + return Objects.requireNonNull(binding.classNameInput.getText()).toString(); } private UmlClass.UmlClassType getClassType() { - if (mJavaRadio.isChecked()) return UmlClass.UmlClassType.JAVA_CLASS; - if (mAbstractRadio.isChecked()) return UmlClass.UmlClassType.ABSTRACT_CLASS; - if (mInterfaceRadio.isChecked()) return UmlClass.UmlClassType.INTERFACE; + if (binding.classJavaRadio.isChecked()) return UmlClass.UmlClassType.JAVA_CLASS; + if (binding.classAbstractRadio.isChecked()) return UmlClass.UmlClassType.ABSTRACT_CLASS; + if (binding.classInterfaceRadio.isChecked()) return UmlClass.UmlClassType.INTERFACE; return UmlClass.UmlClassType.ENUM; } @@ -414,134 +395,76 @@ private UmlClass.UmlClassType getClassType() { // ********************************************************************************************** private void startNewValueDialog() { - AlertDialog.Builder adb=new AlertDialog.Builder(getContext()); - adb.setTitle("Add a value") - .setMessage("Enter value :"); - final EditText input=new EditText(getContext()); - adb.setView(input) - .setNegativeButton("CANCEL", new DialogInterface.OnClickListener() { - @Override - public void onClick(DialogInterface dialog, int which) { - - } - }) - .setPositiveButton("OK", new DialogInterface.OnClickListener() { - @Override - public void onClick(DialogInterface dialog, int which) { - mUmlClass.addValue(new UmlEnumValue(input.getText().toString(),mUmlClass.getValueCount())); - updateLists(); - } - }); - Dialog inputDialog=adb.create(); - inputDialog.show(); + final EditText input=new EditText(requireContext()); + new MaterialAlertDialogBuilder(requireContext()) + .setTitle("Add a value") + .setMessage("Enter value :") + .setView(input) + .setNegativeButton("CANCEL", (d, which) -> d.dismiss()) + .setPositiveButton("OK", (d, which) -> { + mUmlClass.addValue(new UmlEnumValue(input.getText().toString(),mUmlClass.getValueCount())); + updateLists(); + }).show(); } private void startDeleteClassDialog() { final Fragment fragment=this; - AlertDialog.Builder builder=new AlertDialog.Builder(getContext()); - builder.setTitle("Delete class ?") - .setMessage("Are you sure you want to delete this class ?"); - builder.setNegativeButton("NO", new DialogInterface.OnClickListener() { - @Override - public void onClick(DialogInterface dialog, int which) { - - } - }); - builder.setPositiveButton("YES", new DialogInterface.OnClickListener() { - @Override - public void onClick(DialogInterface dialog, int which) { - mCallback.getProject().removeUmlClass(mUmlClass); - mCallback.closeClassEditorFragment(fragment); - } - }); - AlertDialog dialog=builder.create(); - dialog.show(); + new MaterialAlertDialogBuilder(requireContext()) + .setTitle("Delete class ?") + .setMessage("Are you sure you want to delete this class ?") + .setNegativeButton("NO", (d, i) -> d.dismiss()) + .setPositiveButton("YES", (dialog, i) -> { + mCallback.getProject().removeUmlClass(mUmlClass); + mCallback.closeClassEditorFragment(fragment); + }).show(); } private void startRenameValueDialog(final int valueOrder) { - AlertDialog.Builder builder=new AlertDialog.Builder(getContext()); final EditText editText=new EditText(getContext()); - builder.setView(editText) + + new MaterialAlertDialogBuilder(requireContext()) + .setView(editText) .setTitle("Rename Enum value") .setMessage("Enter a new name :") - .setNegativeButton("CANCEL", new DialogInterface.OnClickListener() { - @Override - public void onClick(DialogInterface dialogInterface, int i) { - - } - }) - .setPositiveButton("OK", new DialogInterface.OnClickListener() { - @Override - public void onClick(DialogInterface dialogInterface, int i) { - mUmlClass.findValueByOrder(valueOrder).setName(editText.getText().toString()); - updateLists(); - } + .setNegativeButton("CANCEL", (d, i) -> d.dismiss()) + .setPositiveButton("OK", (d, i) -> { + mUmlClass.findValueByOrder(valueOrder).setName(editText.getText().toString()); + updateLists(); }) - .create() .show(); } private void startDeleteValueDialog(final int valueOrder) { - AlertDialog.Builder builder=new AlertDialog.Builder(getContext()); - builder.setTitle("Delete value ?") - .setMessage("Are you sure you want to delete this value ?") - .setNegativeButton("NO", new DialogInterface.OnClickListener() { - @Override - public void onClick(DialogInterface dialog, int which) { - - } - }) - .setPositiveButton("YES", new DialogInterface.OnClickListener() { - @Override - public void onClick(DialogInterface dialog, int which) { + new MaterialAlertDialogBuilder(requireContext()) + .setTitle("Delete value ?") + .setMessage("Are you sure you want to delete this value ?") + .setNegativeButton("NO", (dialog, i) -> dialog.dismiss()) + .setPositiveButton("YES", (d, i) -> { mUmlClass.removeValue(mUmlClass.findValueByOrder(valueOrder)); updateLists(); - } - }); - AlertDialog dialog=builder.create(); - dialog.show(); + }).show(); } private void startDeleteAttributeDialog(final int attributeOrder) { - AlertDialog.Builder builder=new AlertDialog.Builder(getContext()); - builder.setTitle("Delete attribute ?") + new MaterialAlertDialogBuilder(requireContext()) + .setTitle("Delete attribute ?") .setMessage("Are you sure you want to delete this attribute ?") - .setNegativeButton("NO", new DialogInterface.OnClickListener() { - @Override - public void onClick(DialogInterface dialog, int which) { - - } - }) - .setPositiveButton("YES", new DialogInterface.OnClickListener() { - @Override - public void onClick(DialogInterface dialog, int which) { - mUmlClass.removeAttribute(mUmlClass.findAttributeByOrder(attributeOrder)); - updateLists(); - } - }); - AlertDialog dialog=builder.create(); - dialog.show(); + .setNegativeButton("NO", (d, which) -> d.dismiss()) + .setPositiveButton("YES", (d, which) -> { + mUmlClass.removeAttribute(mUmlClass.findAttributeByOrder(attributeOrder)); + updateLists(); + }).show(); } private void startDeleteMethodDialog(final int methodOrder) { - AlertDialog.Builder builder=new AlertDialog.Builder(getContext()); - builder.setTitle("Delete method ?") + new MaterialAlertDialogBuilder(requireContext()) + .setTitle("Delete method ?") .setMessage("Are you sure you want to delete this method ?") - .setNegativeButton("NO", new DialogInterface.OnClickListener() { - @Override - public void onClick(DialogInterface dialog, int which) { - - } - }) - .setPositiveButton("YES", new DialogInterface.OnClickListener() { - @Override - public void onClick(DialogInterface dialog, int which) { - mUmlClass.removeMethod(mUmlClass.findMethodByOrder(methodOrder)); - updateLists(); - } - }); - AlertDialog dialog=builder.create(); - dialog.show(); + .setNegativeButton("NO", (d, which) -> d.dismiss()) + .setPositiveButton("YES", (d, which) -> { + mUmlClass.removeMethod(mUmlClass.findMethodByOrder(methodOrder)); + updateLists(); + }).show(); } diff --git a/app/src/main/java/com/nathaniel/motus/umlclasseditor/view/CrashActivity.java b/app/src/main/java/com/nathaniel/motus/umlclasseditor/view/CrashActivity.java new file mode 100644 index 0000000..e01b28b --- /dev/null +++ b/app/src/main/java/com/nathaniel/motus/umlclasseditor/view/CrashActivity.java @@ -0,0 +1,37 @@ +package com.nathaniel.motus.umlclasseditor.view; + +import androidx.appcompat.app.AppCompatActivity; + +import android.app.Activity; +import android.content.ComponentName; +import android.content.Context; +import android.content.Intent; +import android.content.pm.PackageManager; +import android.os.Bundle; + +import com.nathaniel.motus.umlclasseditor.R; +import com.nathaniel.motus.umlclasseditor.databinding.ActivityCrashBinding; + +public class CrashActivity extends AppCompatActivity { + private ActivityCrashBinding binding; + @Override + protected void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + binding = ActivityCrashBinding.inflate(getLayoutInflater()); + setContentView(binding.getRoot()); + + binding.logs.setText(getIntent().getExtras().containsKey("ex") ? getIntent().getStringExtra("ex") : ""); + + binding.restartBtn.setOnClickListener(v->triggerRebirth(this)); + } + + void triggerRebirth(Context context) { + PackageManager packageManager = context.getPackageManager(); + Intent intent = packageManager.getLaunchIntentForPackage(context.getPackageName()); + ComponentName componentName = intent.getComponent(); + Intent mainIntent = Intent.makeRestartActivityTask(componentName); + mainIntent.setPackage(context.getPackageName()); + context.startActivity(mainIntent); + Runtime.getRuntime().exit(0); + } +} \ No newline at end of file diff --git a/app/src/main/java/com/nathaniel/motus/umlclasseditor/view/GraphFragment.java b/app/src/main/java/com/nathaniel/motus/umlclasseditor/view/GraphFragment.java index 257c434..b90b556 100644 --- a/app/src/main/java/com/nathaniel/motus/umlclasseditor/view/GraphFragment.java +++ b/app/src/main/java/com/nathaniel/motus/umlclasseditor/view/GraphFragment.java @@ -11,10 +11,12 @@ import android.view.ViewGroup; import android.widget.Button; import android.widget.ImageButton; +import android.widget.LinearLayout; import android.widget.TextView; import com.nathaniel.motus.umlclasseditor.R; import com.nathaniel.motus.umlclasseditor.controller.FragmentObserver; +import com.nathaniel.motus.umlclasseditor.controller.MainActivity; import com.nathaniel.motus.umlclasseditor.model.UmlClass; import com.nathaniel.motus.umlclasseditor.model.UmlRelation; @@ -22,6 +24,7 @@ public class GraphFragment extends Fragment implements View.OnClickListener { private GraphView mGraphView; private TextView mGraphText; + private TextView mNewClassLayout; private ImageButton mInheritanceButton; private ImageButton mRealizationButton; private ImageButton mAggregationButton; @@ -30,6 +33,7 @@ public class GraphFragment extends Fragment implements View.OnClickListener { private ImageButton mDependancyButton; private ImageButton mCompositionButton; private Button mNewClassButton; + private LinearLayout optionsLayout; private boolean mExpectingTouchLocation =false; private boolean mExpectingStartClass=false; @@ -188,6 +192,9 @@ private void configureViews() { mNewClassButton=getActivity().findViewById(R.id.new_class_button); mNewClassButton.setTag(NEW_CLASS_BUTTON_TAG); mNewClassButton.setOnClickListener(this); + + mNewClassLayout = getActivity().findViewById(R.id.locateNewClassLayout); + optionsLayout = getActivity().findViewById(R.id.optionsLayout); } private void createCallbackToParentActivity() { @@ -204,6 +211,7 @@ public void setPrompt(String prompt) { public void clearPrompt() { mGraphText.setText(""); + toggleLocateClass(false); } // ********************************************************************************************** @@ -220,6 +228,7 @@ public void onClick(View v) { case NEW_CLASS_BUTTON_TAG: this.setExpectingTouchLocation(true); this.setPrompt("Locate the new class"); + toggleLocateClass(true); break; case INHERITANCE_BUTTON_TAG: @@ -270,4 +279,11 @@ private void clearInput() { clearPrompt(); } + public void toggleLocateClass(boolean is_locate){ + MainActivity.hideToolBar(is_locate); + optionsLayout.setVisibility(is_locate?View.GONE:View.VISIBLE); + mNewClassLayout.setVisibility(is_locate?View.VISIBLE:View.GONE); + mNewClassLayout.setText(mGraphText.getText()); + } + } \ No newline at end of file diff --git a/app/src/main/java/com/nathaniel/motus/umlclasseditor/view/GraphView.java b/app/src/main/java/com/nathaniel/motus/umlclasseditor/view/GraphView.java index 6c4aefd..0392693 100644 --- a/app/src/main/java/com/nathaniel/motus/umlclasseditor/view/GraphView.java +++ b/app/src/main/java/com/nathaniel/motus/umlclasseditor/view/GraphView.java @@ -11,12 +11,12 @@ import android.graphics.Path; import android.graphics.Typeface; import android.util.AttributeSet; -import android.util.Log; import android.view.MotionEvent; import android.view.View; import androidx.annotation.Nullable; +import com.google.android.material.dialog.MaterialAlertDialogBuilder; import com.nathaniel.motus.umlclasseditor.R; import com.nathaniel.motus.umlclasseditor.model.UmlClass; import com.nathaniel.motus.umlclasseditor.model.UmlClassAttribute; @@ -25,9 +25,11 @@ import com.nathaniel.motus.umlclasseditor.model.UmlProject; import com.nathaniel.motus.umlclasseditor.model.UmlRelation; -public class GraphView extends View implements View.OnTouchListener{ +import java.util.Random; - enum TouchMode{DRAG,ZOOM} +public class GraphView extends View implements View.OnTouchListener { + + enum TouchMode {DRAG, ZOOM} private GraphFragment mGraphFragment; private float mZoom; @@ -38,7 +40,7 @@ enum TouchMode{DRAG,ZOOM} private float mLastTouchY; private float mOldDist; private float mNewDist; - private TouchMode mTouchMode=TouchMode.DRAG; + private TouchMode mTouchMode = TouchMode.DRAG; private int mPrimaryPointerIndex; private float mXMidPoint; private float mYMidpoint; @@ -51,23 +53,28 @@ enum TouchMode{DRAG,ZOOM} private Paint dashPaint; private Paint solidBlackPaint; private Paint solidWhitePaint; + + private Paint headerTextPaint; + + private boolean isBoxSelected = false; + private UmlClass mMovingClass; private GraphViewObserver mCallback; private long mActionDownEventTime; - private long mFirstClickTime=0; - private static final long CLICK_DELAY=200; - private static final long DOUBLE_CLICK_DELAY=500; - private static final float DOUBLE_CLICK_DISTANCE_MAX=10; - private float mFirstClickX=0; - private float mFirstClickY=0; + private long mFirstClickTime = 0; + private static final long CLICK_DELAY = 200; + private static final long DOUBLE_CLICK_DELAY = 500; + private static final float DOUBLE_CLICK_DISTANCE_MAX = 10; + private float mFirstClickX = 0; + private float mFirstClickY = 0; // ********************************************************************************************** // Standard drawing dimensions (in dp) // ********************************************************************************************** - private static final float FONT_SIZE=20; - private static final float INTERLINE=10; - private static final float ARROW_SIZE=10; + private static final float FONT_SIZE = 20; + private static final float INTERLINE = 10; + private static final float ARROW_SIZE = 10; // ********************************************************************************************** @@ -76,12 +83,12 @@ enum TouchMode{DRAG,ZOOM} public GraphView(Context context) { super(context); - init(-1,-1,-1); + init(-1, -1, -1); } public GraphView(Context context, float zoom, int xOffset, int yOffset) { super(context); - init(zoom,xOffset,yOffset); + init(zoom, xOffset, yOffset); } public GraphView(Context context, @Nullable AttributeSet attrs, int defStyleAttr) { @@ -95,70 +102,76 @@ public GraphView(Context context, @Nullable AttributeSet attrs) { } private void init(float zoom, int xOffset, int yOffset) { - if (zoom!=-1) - mZoom=zoom; + if (zoom != -1) + mZoom = zoom; else - mZoom=1; + mZoom = 1; - if (xOffset!=-1) - mXOffset=xOffset; + if (xOffset != -1) + mXOffset = xOffset; else - mXOffset=0; + mXOffset = 0; - if (yOffset!=-1) - mYOffset=yOffset; + if (yOffset != -1) + mYOffset = yOffset; else - mYOffset=0; + mYOffset = 0; - plainTextPaint =new Paint(); + plainTextPaint = new Paint(); plainTextPaint.setColor(Color.DKGRAY); - italicTextPaint=new Paint(); + italicTextPaint = new Paint(); italicTextPaint.setColor(Color.DKGRAY); italicTextPaint.setTypeface(Typeface.defaultFromStyle(Typeface.ITALIC)); - underlinedTextPaint=new Paint(); + underlinedTextPaint = new Paint(); underlinedTextPaint.setColor(Color.DKGRAY); underlinedTextPaint.setFlags(Paint.UNDERLINE_TEXT_FLAG); - linePaint =new Paint(); + linePaint = new Paint(); linePaint.setColor(Color.DKGRAY); linePaint.setStyle(Paint.Style.STROKE); - dashPaint=new Paint(); + dashPaint = new Paint(); dashPaint.setColor(Color.DKGRAY); dashPaint.setStyle(Paint.Style.STROKE); - dashPaint.setPathEffect(new DashPathEffect(new float[]{10f,10f},0)); + dashPaint.setPathEffect(new DashPathEffect(new float[]{10f, 10f}, 0)); - solidBlackPaint=new Paint(); + solidBlackPaint = new Paint(); solidBlackPaint.setColor(Color.DKGRAY); solidBlackPaint.setStyle(Paint.Style.FILL_AND_STROKE); - solidWhitePaint=new Paint(); + solidWhitePaint = new Paint(); solidWhitePaint.setColor(Color.WHITE); solidWhitePaint.setStyle(Paint.Style.FILL); + headerTextPaint = new Paint(); + headerTextPaint.setColor(Color.WHITE); + setOnTouchListener(this); createCallbackToParentActivity(); } private void init(AttributeSet attrs) { - TypedArray attr=getContext().obtainStyledAttributes(attrs, R.styleable.GraphView); - float zoom=attr.getFloat(R.styleable.GraphView_zoom,-1); - int xOffset=attr.getInt(R.styleable.GraphView_xOffset,-1); - int yOffset=attr.getInt(R.styleable.GraphView_yOffset,-1); + TypedArray attr = getContext().obtainStyledAttributes(attrs, R.styleable.GraphView); + float zoom = attr.getFloat(R.styleable.GraphView_zoom, -1); + int xOffset = attr.getInt(R.styleable.GraphView_xOffset, -1); + int yOffset = attr.getInt(R.styleable.GraphView_yOffset, -1); - init(zoom,xOffset,yOffset); + init(zoom, xOffset, yOffset); } // ********************************************************************************************** // Callback interface // ********************************************************************************************** - public interface GraphViewObserver{ + public interface GraphViewObserver { public boolean isExpectingTouchLocation(); + public void createClass(float xLocation, float yLocation); + public void editClass(UmlClass umlClass); + public void createRelation(UmlClass startClass, UmlClass endClass, UmlRelation.UmlRelationType relationType); } @@ -168,9 +181,9 @@ public interface GraphViewObserver{ public void setUmlProject(UmlProject umlProject) { mUmlProject = umlProject; - mZoom=mUmlProject.getZoom(); - mXOffset=mUmlProject.getXOffset(); - mYOffset=mUmlProject.getYOffset(); + mZoom = mUmlProject.getZoom(); + mXOffset = mUmlProject.getXOffset(); + mYOffset = mUmlProject.getYOffset(); this.invalidate(); } @@ -211,18 +224,21 @@ protected void onDraw(Canvas canvas) { // Drawing methods // ********************************************************************************************** - public void drawUmlClass(Canvas canvas,UmlClass umlClass) { + public void drawUmlClass(Canvas canvas, UmlClass umlClass) { + + plainTextPaint.setTextSize(FONT_SIZE * mZoom); + italicTextPaint.setTextSize(FONT_SIZE * mZoom); + underlinedTextPaint.setTextSize(FONT_SIZE * mZoom); - plainTextPaint.setTextSize(FONT_SIZE*mZoom); - italicTextPaint.setTextSize(FONT_SIZE*mZoom); - underlinedTextPaint.setTextSize(FONT_SIZE*mZoom); + // for header text + headerTextPaint.setTextSize(FONT_SIZE * mZoom); //Update class dimensions updateUmlClassNormalDimensions(umlClass); - drawUmlClassHeader(canvas,umlClass); - if (umlClass.getUmlClassType()== UmlClass.UmlClassType.ENUM) - drawValueBox(canvas,umlClass); + drawUmlClassHeader(canvas, umlClass); + if (umlClass.getUmlClassType() == UmlClass.UmlClassType.ENUM) + drawValueBox(canvas, umlClass); else { drawAttributeBox(canvas, umlClass); drawMethodBox(canvas, umlClass); @@ -230,180 +246,191 @@ public void drawUmlClass(Canvas canvas,UmlClass umlClass) { } private void drawUmlClassHeader(Canvas canvas, UmlClass umlClass) { + if (umlClass.getmUmlClassHeaderPaint() == null) { + int randColor = Color.rgb(new Random().nextInt(128), new Random().nextInt(128), new Random().nextInt(128)); + Paint paint = new Paint(); + paint.setColor(randColor); + paint.setStyle(Paint.Style.FILL); + + umlClass.setmUmlClassHeaderPaint(paint); + umlClass.setColorPaint(paint.getColor()); + } + canvas.drawRect(visibleX(umlClass.getUmlClassNormalXPos()), visibleY(umlClass.getUmlClassNormalYPos()), - visibleX(umlClass.getUmlClassNormalXPos()+umlClass.getUmlClassNormalWidth()), - visibleY(umlClass.getUmlClassNormalYPos()+getClassHeaderNormalHeight(umlClass)), - linePaint); + visibleX(umlClass.getUmlClassNormalXPos() + umlClass.getUmlClassNormalWidth()), + visibleY(umlClass.getUmlClassNormalYPos() + getClassHeaderNormalHeight(umlClass)), + umlClass.getmUmlClassHeaderPaint()); switch (umlClass.getUmlClassType()) { case INTERFACE: canvas.drawText("<< Interface >>", - visibleX(umlClass.getUmlClassNormalXPos()+(umlClass.getUmlClassNormalWidth()-getTextNormalWidth("<< Interface >>"))/2), - visibleY(umlClass.getUmlClassNormalYPos()+FONT_SIZE+INTERLINE), - plainTextPaint); + visibleX(umlClass.getUmlClassNormalXPos() + (umlClass.getUmlClassNormalWidth() - getTextNormalWidth("<< Interface >>")) / 2), + visibleY(umlClass.getUmlClassNormalYPos() + FONT_SIZE + INTERLINE), + headerTextPaint); canvas.drawText(umlClass.getName(), - visibleX(umlClass.getUmlClassNormalXPos()+(umlClass.getUmlClassNormalWidth()-getTextNormalWidth(umlClass.getName()))/2), - visibleY(umlClass.getUmlClassNormalYPos()+FONT_SIZE*2+INTERLINE*2), - plainTextPaint); + visibleX(umlClass.getUmlClassNormalXPos() + (umlClass.getUmlClassNormalWidth() - getTextNormalWidth(umlClass.getName())) / 2), + visibleY(umlClass.getUmlClassNormalYPos() + FONT_SIZE * 2 + INTERLINE * 2), + headerTextPaint); break; case ABSTRACT_CLASS: + headerTextPaint.setTypeface(Typeface.defaultFromStyle(Typeface.ITALIC)); canvas.drawText(umlClass.getName(), - visibleX(umlClass.getUmlClassNormalXPos()+(umlClass.getUmlClassNormalWidth()-getTextNormalWidth(umlClass.getName()))/2), - visibleY(umlClass.getUmlClassNormalYPos()+FONT_SIZE+INTERLINE), - italicTextPaint); + visibleX(umlClass.getUmlClassNormalXPos() + (umlClass.getUmlClassNormalWidth() - getTextNormalWidth(umlClass.getName())) / 2), + visibleY(umlClass.getUmlClassNormalYPos() + FONT_SIZE + INTERLINE), + headerTextPaint); break; default: canvas.drawText(umlClass.getName(), - visibleX(umlClass.getUmlClassNormalXPos()+(umlClass.getUmlClassNormalWidth()-getTextNormalWidth(umlClass.getName()))/2), - visibleY(umlClass.getUmlClassNormalYPos()+FONT_SIZE+INTERLINE), - plainTextPaint); + visibleX(umlClass.getUmlClassNormalXPos() + (umlClass.getUmlClassNormalWidth() - getTextNormalWidth(umlClass.getName())) / 2), + visibleY(umlClass.getUmlClassNormalYPos() + FONT_SIZE + INTERLINE), + headerTextPaint); } } private void drawAttributeBox(Canvas canvas, UmlClass umlClass) { canvas.drawRect(visibleX(umlClass.getUmlClassNormalXPos()), - visibleY(umlClass.getUmlClassNormalYPos()+getClassHeaderNormalHeight(umlClass)), - visibleX(umlClass.getUmlClassNormalXPos()+umlClass.getUmlClassNormalWidth()), - visibleY(umlClass.getUmlClassNormalYPos()+getClassHeaderNormalHeight(umlClass)+getAttributeBoxNormalHeight(umlClass)), + visibleY(umlClass.getUmlClassNormalYPos() + getClassHeaderNormalHeight(umlClass)), + visibleX(umlClass.getUmlClassNormalXPos() + umlClass.getUmlClassNormalWidth()), + visibleY(umlClass.getUmlClassNormalYPos() + getClassHeaderNormalHeight(umlClass) + getAttributeBoxNormalHeight(umlClass)), linePaint); - float currentY=umlClass.getUmlClassNormalYPos()+getClassHeaderNormalHeight(umlClass)+INTERLINE+FONT_SIZE; + float currentY = umlClass.getUmlClassNormalYPos() + getClassHeaderNormalHeight(umlClass) + INTERLINE + FONT_SIZE; for (UmlClassAttribute a : umlClass.getAttributes()) { if (a.isStatic()) canvas.drawText(a.getAttributeCompleteString(), - visibleX(umlClass.getUmlClassNormalXPos()+INTERLINE), + visibleX(umlClass.getUmlClassNormalXPos() + INTERLINE), visibleY(currentY), underlinedTextPaint); else canvas.drawText(a.getAttributeCompleteString(), - visibleX(umlClass.getUmlClassNormalXPos()+INTERLINE), + visibleX(umlClass.getUmlClassNormalXPos() + INTERLINE), visibleY(currentY), plainTextPaint); - currentY=currentY+FONT_SIZE+INTERLINE; + currentY = currentY + FONT_SIZE + INTERLINE; } } private void drawMethodBox(Canvas canvas, UmlClass umlClass) { canvas.drawRect(visibleX(umlClass.getUmlClassNormalXPos()), - visibleY(umlClass.getUmlClassNormalYPos()+getClassHeaderNormalHeight(umlClass)+getAttributeBoxNormalHeight(umlClass)), - visibleX(umlClass.getUmlClassNormalXPos()+umlClass.getUmlClassNormalWidth()), - visibleY(umlClass.getUmlClassNormalYPos()+getClassHeaderNormalHeight(umlClass)+getAttributeBoxNormalHeight(umlClass)+getMethodBoxNormalHeight(umlClass)), + visibleY(umlClass.getUmlClassNormalYPos() + getClassHeaderNormalHeight(umlClass) + getAttributeBoxNormalHeight(umlClass)), + visibleX(umlClass.getUmlClassNormalXPos() + umlClass.getUmlClassNormalWidth()), + visibleY(umlClass.getUmlClassNormalYPos() + getClassHeaderNormalHeight(umlClass) + getAttributeBoxNormalHeight(umlClass) + getMethodBoxNormalHeight(umlClass)), linePaint); - float currentY=umlClass.getUmlClassNormalYPos()+getClassHeaderNormalHeight(umlClass)+getAttributeBoxNormalHeight(umlClass)+INTERLINE+FONT_SIZE; + float currentY = umlClass.getUmlClassNormalYPos() + getClassHeaderNormalHeight(umlClass) + getAttributeBoxNormalHeight(umlClass) + INTERLINE + FONT_SIZE; for (UmlClassMethod m : umlClass.getMethods()) { if (m.isStatic()) canvas.drawText(m.getMethodCompleteString(), - visibleX(umlClass.getUmlClassNormalXPos()+INTERLINE), + visibleX(umlClass.getUmlClassNormalXPos() + INTERLINE), visibleY(currentY), underlinedTextPaint); else canvas.drawText(m.getMethodCompleteString(), - visibleX(umlClass.getUmlClassNormalXPos()+INTERLINE), + visibleX(umlClass.getUmlClassNormalXPos() + INTERLINE), visibleY(currentY), plainTextPaint); - currentY=currentY+FONT_SIZE+INTERLINE; + currentY = currentY + FONT_SIZE + INTERLINE; } } private void drawValueBox(Canvas canvas, UmlClass umlClass) { canvas.drawRect(visibleX(umlClass.getUmlClassNormalXPos()), - visibleY(umlClass.getUmlClassNormalYPos()+getClassHeaderNormalHeight(umlClass)), - visibleX(umlClass.getUmlClassNormalXPos()+umlClass.getUmlClassNormalWidth()), - visibleY(umlClass.getUmlClassNormalYPos()+getClassHeaderNormalHeight(umlClass)+getValueBoxNormalHeight(umlClass)), + visibleY(umlClass.getUmlClassNormalYPos() + getClassHeaderNormalHeight(umlClass)), + visibleX(umlClass.getUmlClassNormalXPos() + umlClass.getUmlClassNormalWidth()), + visibleY(umlClass.getUmlClassNormalYPos() + getClassHeaderNormalHeight(umlClass) + getValueBoxNormalHeight(umlClass)), linePaint); - float currentY=umlClass.getUmlClassNormalYPos()+getClassHeaderNormalHeight(umlClass)+INTERLINE+FONT_SIZE; + float currentY = umlClass.getUmlClassNormalYPos() + getClassHeaderNormalHeight(umlClass) + INTERLINE + FONT_SIZE; for (UmlEnumValue v : umlClass.getValues()) { canvas.drawText(v.getName(), - visibleX(umlClass.getUmlClassNormalXPos()+INTERLINE), + visibleX(umlClass.getUmlClassNormalXPos() + INTERLINE), visibleY(currentY), plainTextPaint); - currentY=currentY+FONT_SIZE+INTERLINE; + currentY = currentY + FONT_SIZE + INTERLINE; } } - private void drawRelation(Canvas canvas,UmlRelation umlRelation) { + private void drawRelation(Canvas canvas, UmlRelation umlRelation) { - float originAbsoluteLeft=umlRelation.getRelationOriginClass().getUmlClassNormalXPos(); - float originAbsoluteRight=umlRelation.getRelationOriginClass().getNormalRightEnd(); - float originAbsoluteTop=umlRelation.getRelationOriginClass().getUmlClassNormalYPos(); - float originAbsoluteBottom=umlRelation.getRelationOriginClass().getNormalBottomEnd(); - float endAbsoluteLeft=umlRelation.getRelationEndClass().getUmlClassNormalXPos(); - float endAbsoluteRight=umlRelation.getRelationEndClass().getNormalRightEnd(); - float endAbsoluteTop=umlRelation.getRelationEndClass().getUmlClassNormalYPos(); - float endAbsoluteBottom=umlRelation.getRelationEndClass().getNormalBottomEnd(); - float absoluteXOrigin=0; - float absoluteYOrigin=0; - float absoluteXEnd=0; - float absoluteYEnd=0; + float originAbsoluteLeft = umlRelation.getRelationOriginClass().getUmlClassNormalXPos(); + float originAbsoluteRight = umlRelation.getRelationOriginClass().getNormalRightEnd(); + float originAbsoluteTop = umlRelation.getRelationOriginClass().getUmlClassNormalYPos(); + float originAbsoluteBottom = umlRelation.getRelationOriginClass().getNormalBottomEnd(); + float endAbsoluteLeft = umlRelation.getRelationEndClass().getUmlClassNormalXPos(); + float endAbsoluteRight = umlRelation.getRelationEndClass().getNormalRightEnd(); + float endAbsoluteTop = umlRelation.getRelationEndClass().getUmlClassNormalYPos(); + float endAbsoluteBottom = umlRelation.getRelationEndClass().getNormalBottomEnd(); + float absoluteXOrigin = 0; + float absoluteYOrigin = 0; + float absoluteXEnd = 0; + float absoluteYEnd = 0; //End in South quarter of Origin if (umlRelation.getRelationEndClass().isSouthOf(umlRelation.getRelationOriginClass())) { - float lowerXLimit= originAbsoluteLeft-endAbsoluteTop+originAbsoluteBottom-umlRelation.getRelationEndClass().getUmlClassNormalWidth(); - float upperXLimit=originAbsoluteRight+endAbsoluteTop-originAbsoluteBottom; + float lowerXLimit = originAbsoluteLeft - endAbsoluteTop + originAbsoluteBottom - umlRelation.getRelationEndClass().getUmlClassNormalWidth(); + float upperXLimit = originAbsoluteRight + endAbsoluteTop - originAbsoluteBottom; - absoluteXEnd=endAbsoluteRight- - umlRelation.getRelationEndClass().getUmlClassNormalWidth()/(upperXLimit-lowerXLimit)* - (endAbsoluteLeft-lowerXLimit); - absoluteYEnd=endAbsoluteTop; + absoluteXEnd = endAbsoluteRight - + umlRelation.getRelationEndClass().getUmlClassNormalWidth() / (upperXLimit - lowerXLimit) * + (endAbsoluteLeft - lowerXLimit); + absoluteYEnd = endAbsoluteTop; - absoluteXOrigin=originAbsoluteLeft+ - umlRelation.getRelationOriginClass().getUmlClassNormalWidth()/(upperXLimit-lowerXLimit)* - (endAbsoluteLeft-lowerXLimit); + absoluteXOrigin = originAbsoluteLeft + + umlRelation.getRelationOriginClass().getUmlClassNormalWidth() / (upperXLimit - lowerXLimit) * + (endAbsoluteLeft - lowerXLimit); - absoluteYOrigin=originAbsoluteBottom; + absoluteYOrigin = originAbsoluteBottom; } //End in North quarter or Origin if (umlRelation.getRelationEndClass().isNorthOf(umlRelation.getRelationOriginClass())) { - float lowerXLimit=originAbsoluteLeft-originAbsoluteTop+endAbsoluteBottom-umlRelation.getRelationEndClass().getUmlClassNormalWidth(); - float upperXLimit=originAbsoluteRight+originAbsoluteTop-endAbsoluteBottom; + float lowerXLimit = originAbsoluteLeft - originAbsoluteTop + endAbsoluteBottom - umlRelation.getRelationEndClass().getUmlClassNormalWidth(); + float upperXLimit = originAbsoluteRight + originAbsoluteTop - endAbsoluteBottom; - absoluteXEnd=endAbsoluteRight- - umlRelation.getRelationEndClass().getUmlClassNormalWidth()/(upperXLimit-lowerXLimit)* - (endAbsoluteLeft-lowerXLimit); + absoluteXEnd = endAbsoluteRight - + umlRelation.getRelationEndClass().getUmlClassNormalWidth() / (upperXLimit - lowerXLimit) * + (endAbsoluteLeft - lowerXLimit); - absoluteYEnd=endAbsoluteBottom; + absoluteYEnd = endAbsoluteBottom; - absoluteXOrigin=originAbsoluteLeft+ - umlRelation.getRelationOriginClass().getUmlClassNormalWidth()/(upperXLimit-lowerXLimit)* - (endAbsoluteLeft-lowerXLimit); + absoluteXOrigin = originAbsoluteLeft + + umlRelation.getRelationOriginClass().getUmlClassNormalWidth() / (upperXLimit - lowerXLimit) * + (endAbsoluteLeft - lowerXLimit); - absoluteYOrigin=originAbsoluteTop; + absoluteYOrigin = originAbsoluteTop; } //End in West quarter of Origin if (umlRelation.getRelationEndClass().isWestOf(umlRelation.getRelationOriginClass())) { - float lowerYLimit=originAbsoluteTop-originAbsoluteLeft+endAbsoluteRight-umlRelation.getRelationEndClass().getUmlClassNormalHeight(); - float upperYLimit=originAbsoluteBottom+originAbsoluteLeft-endAbsoluteRight; + float lowerYLimit = originAbsoluteTop - originAbsoluteLeft + endAbsoluteRight - umlRelation.getRelationEndClass().getUmlClassNormalHeight(); + float upperYLimit = originAbsoluteBottom + originAbsoluteLeft - endAbsoluteRight; - absoluteXEnd=endAbsoluteRight; + absoluteXEnd = endAbsoluteRight; - absoluteYEnd=endAbsoluteBottom- - umlRelation.getRelationEndClass().getUmlClassNormalHeight()/(upperYLimit-lowerYLimit)* - (endAbsoluteTop-lowerYLimit); + absoluteYEnd = endAbsoluteBottom - + umlRelation.getRelationEndClass().getUmlClassNormalHeight() / (upperYLimit - lowerYLimit) * + (endAbsoluteTop - lowerYLimit); - absoluteXOrigin=originAbsoluteLeft; + absoluteXOrigin = originAbsoluteLeft; - absoluteYOrigin=originAbsoluteTop+ - umlRelation.getRelationOriginClass().getUmlClassNormalHeight()/(upperYLimit-lowerYLimit)* - (endAbsoluteTop-lowerYLimit); + absoluteYOrigin = originAbsoluteTop + + umlRelation.getRelationOriginClass().getUmlClassNormalHeight() / (upperYLimit - lowerYLimit) * + (endAbsoluteTop - lowerYLimit); } //End in East quarter of Origin if (umlRelation.getRelationEndClass().isEastOf(umlRelation.getRelationOriginClass())) { - float lowerYLimit=originAbsoluteTop-endAbsoluteLeft+originAbsoluteRight-umlRelation.getRelationEndClass().getUmlClassNormalHeight(); - float upperYLimit=originAbsoluteBottom+endAbsoluteLeft-originAbsoluteRight; + float lowerYLimit = originAbsoluteTop - endAbsoluteLeft + originAbsoluteRight - umlRelation.getRelationEndClass().getUmlClassNormalHeight(); + float upperYLimit = originAbsoluteBottom + endAbsoluteLeft - originAbsoluteRight; - absoluteXEnd=endAbsoluteLeft; + absoluteXEnd = endAbsoluteLeft; - absoluteYEnd=endAbsoluteBottom- - umlRelation.getRelationEndClass().getUmlClassNormalHeight()/(upperYLimit-lowerYLimit)* - (endAbsoluteTop-lowerYLimit); + absoluteYEnd = endAbsoluteBottom - + umlRelation.getRelationEndClass().getUmlClassNormalHeight() / (upperYLimit - lowerYLimit) * + (endAbsoluteTop - lowerYLimit); - absoluteXOrigin=originAbsoluteRight; + absoluteXOrigin = originAbsoluteRight; - absoluteYOrigin=originAbsoluteTop+ - umlRelation.getRelationOriginClass().getUmlClassNormalHeight()/(upperYLimit-lowerYLimit)* - (endAbsoluteTop-lowerYLimit); + absoluteYOrigin = originAbsoluteTop + + umlRelation.getRelationOriginClass().getUmlClassNormalHeight() / (upperYLimit - lowerYLimit) * + (endAbsoluteTop - lowerYLimit); } //update relation coordinates umlRelation.setXOrigin(absoluteXOrigin); @@ -411,13 +438,13 @@ private void drawRelation(Canvas canvas,UmlRelation umlRelation) { umlRelation.setXEnd(absoluteXEnd); umlRelation.setYEnd(absoluteYEnd); - Path path=new Path(); - path.moveTo(visibleX(absoluteXOrigin),visibleY(absoluteYOrigin)); - path.lineTo(visibleX(absoluteXEnd),visibleY(absoluteYEnd)); + Path path = new Path(); + path.moveTo(visibleX(absoluteXOrigin), visibleY(absoluteYOrigin)); + path.lineTo(visibleX(absoluteXEnd), visibleY(absoluteYEnd)); switch (umlRelation.getUmlRelationType()) { case INHERITANCE: - canvas.drawPath(path,linePaint); + canvas.drawPath(path, linePaint); drawSolidWhiteArrow(canvas, visibleX(absoluteXOrigin), visibleY(absoluteYOrigin), @@ -426,11 +453,11 @@ private void drawRelation(Canvas canvas,UmlRelation umlRelation) { break; case ASSOCIATION: - canvas.drawPath(path,linePaint); + canvas.drawPath(path, linePaint); break; case AGGREGATION: - canvas.drawPath(path,linePaint); + canvas.drawPath(path, linePaint); drawSolidWhiteRhombus(canvas, visibleX(absoluteXOrigin), visibleY(absoluteYOrigin), @@ -439,7 +466,7 @@ private void drawRelation(Canvas canvas,UmlRelation umlRelation) { break; case COMPOSITION: - canvas.drawPath(path,linePaint); + canvas.drawPath(path, linePaint); drawSolidBlackRhombus(canvas, visibleX(absoluteXOrigin), visibleY(absoluteYOrigin), @@ -448,7 +475,7 @@ private void drawRelation(Canvas canvas,UmlRelation umlRelation) { break; case DEPENDENCY: - canvas.drawPath(path,dashPaint); + canvas.drawPath(path, dashPaint); drawArrow(canvas, visibleX(absoluteXOrigin), visibleY(absoluteYOrigin), @@ -457,7 +484,7 @@ private void drawRelation(Canvas canvas,UmlRelation umlRelation) { break; case REALIZATION: - canvas.drawPath(path,dashPaint); + canvas.drawPath(path, dashPaint); drawSolidWhiteArrow(canvas, visibleX(absoluteXOrigin), visibleY(absoluteYOrigin), @@ -470,31 +497,31 @@ private void drawRelation(Canvas canvas,UmlRelation umlRelation) { } } - private void drawArrow(Canvas canvas,float xOrigin, float yOrigin, float xEnd, float yEnd) { + private void drawArrow(Canvas canvas, float xOrigin, float yOrigin, float xEnd, float yEnd) { //draw an arrow at the end of the segment canvas.save(); - canvas.rotate(getAngle(xEnd,yEnd,xOrigin,yOrigin),xEnd,yEnd); - Path path=new Path(); - path.moveTo(xEnd+ARROW_SIZE*mZoom,yEnd-ARROW_SIZE*1.414f/2f*mZoom); - path.lineTo(xEnd,yEnd); - path.lineTo(xEnd+ARROW_SIZE*mZoom,yEnd+ARROW_SIZE*1.414f/2f*mZoom); - canvas.drawPath(path,linePaint); + canvas.rotate(getAngle(xEnd, yEnd, xOrigin, yOrigin), xEnd, yEnd); + Path path = new Path(); + path.moveTo(xEnd + ARROW_SIZE * mZoom, yEnd - ARROW_SIZE * 1.414f / 2f * mZoom); + path.lineTo(xEnd, yEnd); + path.lineTo(xEnd + ARROW_SIZE * mZoom, yEnd + ARROW_SIZE * 1.414f / 2f * mZoom); + canvas.drawPath(path, linePaint); canvas.restore(); } - private void drawSolidWhiteArrow(Canvas canvas,float xOrigin, float yOrigin, float xEnd, float yEnd) { + private void drawSolidWhiteArrow(Canvas canvas, float xOrigin, float yOrigin, float xEnd, float yEnd) { //draw a solid white arrow at the end of the segment canvas.save(); - canvas.rotate(getAngle(xEnd,yEnd,xOrigin,yOrigin),xEnd,yEnd); - Path path=new Path(); - path.moveTo(xEnd,yEnd); - path.lineTo(xEnd+ARROW_SIZE*mZoom,yEnd-ARROW_SIZE*1.414f/2f*mZoom); - path.lineTo(xEnd+ARROW_SIZE*mZoom,yEnd+ARROW_SIZE*1.414f/2f*mZoom); + canvas.rotate(getAngle(xEnd, yEnd, xOrigin, yOrigin), xEnd, yEnd); + Path path = new Path(); + path.moveTo(xEnd, yEnd); + path.lineTo(xEnd + ARROW_SIZE * mZoom, yEnd - ARROW_SIZE * 1.414f / 2f * mZoom); + path.lineTo(xEnd + ARROW_SIZE * mZoom, yEnd + ARROW_SIZE * 1.414f / 2f * mZoom); path.close(); - canvas.drawPath(path,solidWhitePaint); - canvas.drawPath(path,linePaint); + canvas.drawPath(path, solidWhitePaint); + canvas.drawPath(path, linePaint); canvas.restore(); } @@ -502,15 +529,15 @@ private void drawSolidWhiteRhombus(Canvas canvas, float xOrigin, float yOrigin, //draw a solid white rhombus at the end of the segment canvas.save(); - canvas.rotate(getAngle(xEnd,yEnd,xOrigin,yOrigin),xEnd,yEnd); - Path path=new Path(); - path.moveTo(xEnd,yEnd); - path.lineTo(xEnd+ARROW_SIZE*mZoom,yEnd-ARROW_SIZE*1.414f/2f*mZoom); - path.lineTo(xEnd+ARROW_SIZE*2f*mZoom,yEnd); - path.lineTo(xEnd+ARROW_SIZE*mZoom,yEnd+ARROW_SIZE*1.414f/2f*mZoom); + canvas.rotate(getAngle(xEnd, yEnd, xOrigin, yOrigin), xEnd, yEnd); + Path path = new Path(); + path.moveTo(xEnd, yEnd); + path.lineTo(xEnd + ARROW_SIZE * mZoom, yEnd - ARROW_SIZE * 1.414f / 2f * mZoom); + path.lineTo(xEnd + ARROW_SIZE * 2f * mZoom, yEnd); + path.lineTo(xEnd + ARROW_SIZE * mZoom, yEnd + ARROW_SIZE * 1.414f / 2f * mZoom); path.close(); - canvas.drawPath(path,solidWhitePaint); - canvas.drawPath(path,linePaint); + canvas.drawPath(path, solidWhitePaint); + canvas.drawPath(path, linePaint); canvas.restore(); } @@ -518,14 +545,14 @@ private void drawSolidBlackRhombus(Canvas canvas, float xOrigin, float yOrigin, //draw a solid black rhombus at the end of the segment canvas.save(); - canvas.rotate(getAngle(xEnd,yEnd,xOrigin,yOrigin),xEnd,yEnd); - Path path=new Path(); - path.moveTo(xEnd,yEnd); - path.lineTo(xEnd+ARROW_SIZE*mZoom,yEnd-ARROW_SIZE*1.414f/2f*mZoom); - path.lineTo(xEnd+ARROW_SIZE*2f*mZoom,yEnd); - path.lineTo(xEnd+ARROW_SIZE*mZoom,yEnd+ARROW_SIZE*1.414f/2f*mZoom); + canvas.rotate(getAngle(xEnd, yEnd, xOrigin, yOrigin), xEnd, yEnd); + Path path = new Path(); + path.moveTo(xEnd, yEnd); + path.lineTo(xEnd + ARROW_SIZE * mZoom, yEnd - ARROW_SIZE * 1.414f / 2f * mZoom); + path.lineTo(xEnd + ARROW_SIZE * 2f * mZoom, yEnd); + path.lineTo(xEnd + ARROW_SIZE * mZoom, yEnd + ARROW_SIZE * 1.414f / 2f * mZoom); path.close(); - canvas.drawPath(path,solidBlackPaint); + canvas.drawPath(path, solidBlackPaint); canvas.restore(); } @@ -536,61 +563,61 @@ private void drawSolidBlackRhombus(Canvas canvas, float xOrigin, float yOrigin, @Override public boolean onTouch(View v, MotionEvent event) { - int action=event.getActionMasked(); + int action = event.getActionMasked(); switch (action) { case (MotionEvent.ACTION_DOWN): - mActionDownEventTime=event.getEventTime(); - mLastTouchX=event.getX(); - mLastTouchY=event.getY(); - mMovingClass=getTouchedClass(mLastTouchX,mLastTouchY); - mTouchMode=TouchMode.DRAG; - mPrimaryPointerIndex=0; + mActionDownEventTime = event.getEventTime(); + mLastTouchX = event.getX(); + mLastTouchY = event.getY(); + mMovingClass = getTouchedClass(mLastTouchX, mLastTouchY); + mTouchMode = TouchMode.DRAG; + mPrimaryPointerIndex = 0; break; case (MotionEvent.ACTION_POINTER_DOWN): - mOldDist=spacing(event); + mOldDist = spacing(event); calculateMidPoint(event); - mOldXMidPoint=mXMidPoint; - mOldYMidPoint=mYMidpoint; - if (mOldDist>10f) { + mOldXMidPoint = mXMidPoint; + mOldYMidPoint = mYMidpoint; + if (mOldDist > 10f) { mTouchMode = TouchMode.ZOOM; mMovingClass = null; } break; case (MotionEvent.ACTION_MOVE): - if (mTouchMode==TouchMode.DRAG) { + if (mTouchMode == TouchMode.DRAG) { if (mMovingClass == null) { mXOffset = mXOffset + event.getX() - mLastTouchX; mYOffset = mYOffset + event.getY() - mLastTouchY; } else { - mMovingClass.setUmlClassNormalXPos(mMovingClass.getUmlClassNormalXPos()+(event.getX()-mLastTouchX)/mZoom); - mMovingClass.setUmlClassNormalYPos(mMovingClass.getUmlClassNormalYPos()+(event.getY()-mLastTouchY)/mZoom); + mMovingClass.setUmlClassNormalXPos(mMovingClass.getUmlClassNormalXPos() + (event.getX() - mLastTouchX) / mZoom); + mMovingClass.setUmlClassNormalYPos(mMovingClass.getUmlClassNormalYPos() + (event.getY() - mLastTouchY) / mZoom); } - mLastTouchX=event.getX(); - mLastTouchY=event.getY(); + mLastTouchX = event.getX(); + mLastTouchY = event.getY(); } else if (mTouchMode == TouchMode.ZOOM) { - mNewDist=spacing(event); - mZoom=mZoom*mNewDist/mOldDist; + mNewDist = spacing(event); + mZoom = mZoom * mNewDist / mOldDist; calculateMidPoint(event); - mXOffset=mXMidPoint+(mXOffset-mOldXMidPoint)*mNewDist/mOldDist; - mYOffset=mYMidpoint+(mYOffset-mOldYMidPoint)*mNewDist/mOldDist; - mOldDist=mNewDist; - mOldXMidPoint=mXMidPoint; - mOldYMidPoint=mYMidpoint; + mXOffset = mXMidPoint + (mXOffset - mOldXMidPoint) * mNewDist / mOldDist; + mYOffset = mYMidpoint + (mYOffset - mOldYMidPoint) * mNewDist / mOldDist; + mOldDist = mNewDist; + mOldXMidPoint = mXMidPoint; + mOldYMidPoint = mYMidpoint; } break; - case(MotionEvent.ACTION_POINTER_UP): - mTouchMode=TouchMode.DRAG; + case (MotionEvent.ACTION_POINTER_UP): + mTouchMode = TouchMode.DRAG; if (event.getActionIndex() == mPrimaryPointerIndex) { - mPrimaryPointerIndex=(1+mPrimaryPointerIndex)%2; + mPrimaryPointerIndex = (1 + mPrimaryPointerIndex) % 2; } - mLastTouchX=event.getX(mPrimaryPointerIndex); - mLastTouchY=event.getY(mPrimaryPointerIndex); + mLastTouchX = event.getX(mPrimaryPointerIndex); + mLastTouchY = event.getY(mPrimaryPointerIndex); break; case (MotionEvent.ACTION_UP): @@ -598,20 +625,19 @@ public boolean onTouch(View v, MotionEvent event) { //double click if (event.getEventTime() - mActionDownEventTime <= CLICK_DELAY && event.getEventTime() - mFirstClickTime <= DOUBLE_CLICK_DELAY && - distance(mLastTouchX,mLastTouchY,mFirstClickX,mFirstClickY)<=DOUBLE_CLICK_DISTANCE_MAX) { + distance(mLastTouchX, mLastTouchY, mFirstClickX, mFirstClickY) <= DOUBLE_CLICK_DISTANCE_MAX) { if (getTouchedClass(mLastTouchX, mLastTouchY) != null) - mCallback.editClass(getTouchedClass(mLastTouchX,mLastTouchY)); - else if (getTouchedRelation(mLastTouchX,mLastTouchY)!=null) { - promptDeleteRelation(getTouchedRelation(mLastTouchX,mLastTouchY),this); - } - else adjustViewToProject(); + mCallback.editClass(getTouchedClass(mLastTouchX, mLastTouchY)); + else if (getTouchedRelation(mLastTouchX, mLastTouchY) != null) { + promptDeleteRelation(getTouchedRelation(mLastTouchX, mLastTouchY), this); + } else adjustViewToProject(); } //simple click - if (event.getEventTime()-mActionDownEventTime<=CLICK_DELAY) { + if (event.getEventTime() - mActionDownEventTime <= CLICK_DELAY) { mFirstClickTime = event.getEventTime(); - mFirstClickX=event.getX(); - mFirstClickY=event.getY(); + mFirstClickX = event.getX(); + mFirstClickY = event.getY(); //locate new class if (mGraphFragment.isExpectingTouchLocation()) { @@ -621,16 +647,16 @@ else if (getTouchedRelation(mLastTouchX,mLastTouchY)!=null) { //touch relation end class } else if (mGraphFragment.isExpectingEndClass() - && getTouchedClass(mLastTouchX,mLastTouchY)!=null - && getTouchedClass(mLastTouchX,mLastTouchY)!=mGraphFragment.getStartClass()) { - mGraphFragment.setEndClass(getTouchedClass(mLastTouchX,mLastTouchY)); + && getTouchedClass(mLastTouchX, mLastTouchY) != null + && getTouchedClass(mLastTouchX, mLastTouchY) != mGraphFragment.getStartClass()) { + mGraphFragment.setEndClass(getTouchedClass(mLastTouchX, mLastTouchY)); mGraphFragment.setExpectingEndClass(false); mGraphFragment.clearPrompt(); - mCallback.createRelation(mGraphFragment.getStartClass(),mGraphFragment.getEndClass(),mGraphFragment.getUmlRelationType()); + mCallback.createRelation(mGraphFragment.getStartClass(), mGraphFragment.getEndClass(), mGraphFragment.getUmlRelationType()); //touch relation origin class } else if (mGraphFragment.isExpectingStartClass() && getTouchedClass(mLastTouchX, mLastTouchY) != null) { - mGraphFragment.setStartClass(getTouchedClass(mLastTouchX,mLastTouchY)); + mGraphFragment.setStartClass(getTouchedClass(mLastTouchX, mLastTouchY)); mGraphFragment.setExpectingStartClass(false); mGraphFragment.setExpectingEndClass(true); mGraphFragment.setPrompt("Choose end class"); @@ -651,24 +677,23 @@ && getTouchedClass(mLastTouchX,mLastTouchY)!=mGraphFragment.getStartClass()) { // ********************************************************************************************** private void createCallbackToParentActivity() { - mCallback=(GraphViewObserver)this.getContext(); + mCallback = (GraphViewObserver) this.getContext(); } - // ********************************************************************************************** // Calculation methods // ********************************************************************************************** private float spacing(MotionEvent event) { - float dx=event.getX(0)-event.getX(1); - float dy=event.getY(0)-event.getY(1); - return (float) Math.sqrt(dx*dx+dy*dy); + float dx = event.getX(0) - event.getX(1); + float dy = event.getY(0) - event.getY(1); + return (float) Math.sqrt(dx * dx + dy * dy); } private void calculateMidPoint(MotionEvent event) { - mXMidPoint=(event.getX(0)+event.getX(1))/2; - mYMidpoint=(event.getY(0)+event.getY(1))/2; + mXMidPoint = (event.getX(0) + event.getX(1)) / 2; + mYMidpoint = (event.getY(0) + event.getY(1)) / 2; } private void updateUmlClassNormalDimensions(UmlClass umlClass) { @@ -679,16 +704,19 @@ private void updateUmlClassNormalDimensions(UmlClass umlClass) { // umlClass.setUmlClassNormalHeight(INTERLINE*3f+(FONT_SIZE+INTERLINE)*(1f+umlClass.getAttributeList().size()+umlClass.getMethodList().size())); switch (umlClass.getUmlClassType()) { case ENUM: - umlClass.setUmlClassNormalWidth(Math.max(getClassHeaderNormalWidth(umlClass),getValueBoxNormalWidth(umlClass))); - umlClass.setUmlClassNormalHeight(getClassHeaderNormalHeight(umlClass)+getValueBoxNormalHeight(umlClass)); + umlClass.setUmlClassNormalWidth(Math.max(getClassHeaderNormalWidth(umlClass), getValueBoxNormalWidth(umlClass))); + umlClass.setUmlClassNormalHeight(getClassHeaderNormalHeight(umlClass) + getValueBoxNormalHeight(umlClass)); break; default: - float currentWidth=0; - if (getClassHeaderNormalWidth(umlClass)>currentWidth) currentWidth=getClassHeaderNormalWidth(umlClass); - if (getAttributeBoxNormalWidth(umlClass)>currentWidth) currentWidth=getAttributeBoxNormalWidth(umlClass); - if (getMethodBoxNormalWidth(umlClass)>currentWidth) currentWidth=getMethodBoxNormalWidth(umlClass); + float currentWidth = 0; + if (getClassHeaderNormalWidth(umlClass) > currentWidth) + currentWidth = getClassHeaderNormalWidth(umlClass); + if (getAttributeBoxNormalWidth(umlClass) > currentWidth) + currentWidth = getAttributeBoxNormalWidth(umlClass); + if (getMethodBoxNormalWidth(umlClass) > currentWidth) + currentWidth = getMethodBoxNormalWidth(umlClass); umlClass.setUmlClassNormalWidth(currentWidth); - umlClass.setUmlClassNormalHeight(getClassHeaderNormalHeight(umlClass)+getAttributeBoxNormalHeight(umlClass)+getMethodBoxNormalHeight(umlClass)); + umlClass.setUmlClassNormalHeight(getClassHeaderNormalHeight(umlClass) + getAttributeBoxNormalHeight(umlClass) + getMethodBoxNormalHeight(umlClass)); break; } } @@ -699,131 +727,134 @@ private float getClassHeaderNormalWidth(UmlClass umlClass) { case INTERFACE: return Math.max(getTextNormalWidth("<< Interface >>"), getTextNormalWidth(umlClass.getName())) + 2 * INTERLINE; default: - return getTextNormalWidth(umlClass.getName())+2*INTERLINE; + return getTextNormalWidth(umlClass.getName()) + 2 * INTERLINE; } } private float getClassHeaderNormalHeight(UmlClass umlClass) { switch (umlClass.getUmlClassType()) { case INTERFACE: - return FONT_SIZE*2+3*INTERLINE; + return FONT_SIZE * 2 + 3 * INTERLINE; default: - return FONT_SIZE+2*INTERLINE; + return FONT_SIZE + 2 * INTERLINE; } } private float getAttributeBoxNormalWidth(UmlClass umlClass) { - float currentWidth=0; - for (UmlClassAttribute a:umlClass.getAttributes()) - if (getTextNormalWidth(a.getAttributeCompleteString())>currentWidth) - currentWidth=getTextNormalWidth(a.getAttributeCompleteString()); + float currentWidth = 0; + for (UmlClassAttribute a : umlClass.getAttributes()) + if (getTextNormalWidth(a.getAttributeCompleteString()) > currentWidth) + currentWidth = getTextNormalWidth(a.getAttributeCompleteString()); - return currentWidth+2*INTERLINE; + return currentWidth + 2 * INTERLINE; } private float getAttributeBoxNormalHeight(UmlClass umlClass) { - return umlClass.getAttributes().size()*FONT_SIZE+(umlClass.getAttributes().size()+1)*INTERLINE; + return umlClass.getAttributes().size() * FONT_SIZE + (umlClass.getAttributes().size() + 1) * INTERLINE; } private float getMethodBoxNormalWidth(UmlClass umlClass) { - float currentWidth=0; - for (UmlClassMethod m:umlClass.getMethods()) - if (getTextNormalWidth(m.getMethodCompleteString())>currentWidth) - currentWidth=getTextNormalWidth(m.getMethodCompleteString()); + float currentWidth = 0; + for (UmlClassMethod m : umlClass.getMethods()) + if (getTextNormalWidth(m.getMethodCompleteString()) > currentWidth) + currentWidth = getTextNormalWidth(m.getMethodCompleteString()); - return currentWidth+2*INTERLINE; + return currentWidth + 2 * INTERLINE; } private float getMethodBoxNormalHeight(UmlClass umlClass) { - return umlClass.getMethods().size()*FONT_SIZE+(umlClass.getMethods().size()+1)*INTERLINE; + return umlClass.getMethods().size() * FONT_SIZE + (umlClass.getMethods().size() + 1) * INTERLINE; } private float getValueBoxNormalWidth(UmlClass umlClass) { - float currentWidth=0; - for (UmlEnumValue v:umlClass.getValues()) - if (getTextNormalWidth(v.getName())>currentWidth) - currentWidth=getTextNormalWidth(v.getName()); + float currentWidth = 0; + for (UmlEnumValue v : umlClass.getValues()) + if (getTextNormalWidth(v.getName()) > currentWidth) + currentWidth = getTextNormalWidth(v.getName()); - return currentWidth+2*INTERLINE; + return currentWidth + 2 * INTERLINE; } private float getValueBoxNormalHeight(UmlClass umlClass) { - return umlClass.getValues().size()*FONT_SIZE+(umlClass.getValues().size()+1)*INTERLINE; + return umlClass.getValues().size() * FONT_SIZE + (umlClass.getValues().size() + 1) * INTERLINE; } private float getTextNormalWidth(String text) { - plainTextPaint.setTextSize(FONT_SIZE*mZoom); - return plainTextPaint.measureText(text)/mZoom; + plainTextPaint.setTextSize(FONT_SIZE * mZoom); + return plainTextPaint.measureText(text) / mZoom; } private float getAngle(float xOrigin, float yOrigin, float xEnd, float yEnd) { //calculate angle between segment and horizontal - return (float)(Math.copySign(Math.abs(Math.acos((xEnd-xOrigin)/Math.sqrt((xEnd-xOrigin)*(xEnd-xOrigin)+(yEnd-yOrigin)*(yEnd-yOrigin)))),yEnd-yOrigin)/ - Math.PI*180f); + return (float) (Math.copySign(Math.abs(Math.acos((xEnd - xOrigin) / Math.sqrt((xEnd - xOrigin) * (xEnd - xOrigin) + (yEnd - yOrigin) * (yEnd - yOrigin)))), yEnd - yOrigin) / + Math.PI * 180f); } private float getAbsoluteProjectWidth() { //return the length of the rectangle that can contain all the project - float minX=1000000; - float maxX=-1000000; + float minX = 1000000; + float maxX = -1000000; for (UmlClass c : mUmlProject.getUmlClasses()) { - minX=Math.min(c.getUmlClassNormalXPos(),minX); - maxX=Math.max(c.getNormalRightEnd(),maxX); + minX = Math.min(c.getUmlClassNormalXPos(), minX); + maxX = Math.max(c.getNormalRightEnd(), maxX); } - return maxX-minX; + return maxX - minX; } private float getAbsoluteProjectHeight() { //return the height of the rectangle that can contain all the project - float minY=1000000; - float maxY=-1000000; + float minY = 1000000; + float maxY = -1000000; for (UmlClass c : mUmlProject.getUmlClasses()) { - minY=Math.min(c.getUmlClassNormalYPos(),minY); - maxY=Math.max(c.getNormalBottomEnd(),maxY); + minY = Math.min(c.getUmlClassNormalYPos(), minY); + maxY = Math.max(c.getNormalBottomEnd(), maxY); } - return maxY-minY; + return maxY - minY; } private float getAbsoluteProjectLeft() { - float minX=1000000; - for (UmlClass c : mUmlProject.getUmlClasses()) minX=Math.min(c.getUmlClassNormalXPos(),minX); + float minX = 1000000; + for (UmlClass c : mUmlProject.getUmlClasses()) + minX = Math.min(c.getUmlClassNormalXPos(), minX); return minX; } private float getAbsoluteProjectRight() { - float maxX=-1000000; - for (UmlClass c : mUmlProject.getUmlClasses()) maxX=Math.max(c.getNormalRightEnd(),maxX); + float maxX = -1000000; + for (UmlClass c : mUmlProject.getUmlClasses()) maxX = Math.max(c.getNormalRightEnd(), maxX); return maxX; } private float getAbsoluteProjectTop() { - float minY=1000000; - for (UmlClass c : mUmlProject.getUmlClasses()) minY=Math.min(c.getUmlClassNormalYPos(),minY); + float minY = 1000000; + for (UmlClass c : mUmlProject.getUmlClasses()) + minY = Math.min(c.getUmlClassNormalYPos(), minY); return minY; } private float getAbsoluteProjectBottom() { - float maxY=-1000000; - for (UmlClass c : mUmlProject.getUmlClasses()) maxY=Math.max(c.getNormalBottomEnd(),maxY); + float maxY = -1000000; + for (UmlClass c : mUmlProject.getUmlClasses()) + maxY = Math.max(c.getNormalBottomEnd(), maxY); return maxY; } - private void adjustViewToProject() { - float xZoom=this.getMeasuredWidth()/getAbsoluteProjectWidth(); - float yZoom=this.getMeasuredHeight()/getAbsoluteProjectHeight(); + public void adjustViewToProject() { + float xZoom = this.getMeasuredWidth() / getAbsoluteProjectWidth(); + float yZoom = this.getMeasuredHeight() / getAbsoluteProjectHeight(); if (xZoom <= yZoom) { mZoom = xZoom; - mXOffset=-getAbsoluteProjectLeft()*mZoom; - mYOffset =-getAbsoluteProjectTop()*mZoom+(this.getMeasuredHeight()-getAbsoluteProjectHeight()*mZoom)/2f; + mXOffset = -getAbsoluteProjectLeft() * mZoom; + mYOffset = -getAbsoluteProjectTop() * mZoom + (this.getMeasuredHeight() - getAbsoluteProjectHeight() * mZoom) / 2f; } else { - mZoom=yZoom; - mYOffset=-getAbsoluteProjectTop()*mZoom; - mXOffset=-getAbsoluteProjectLeft()*mZoom+(this.getMeasuredWidth()-getAbsoluteProjectWidth()*mZoom)/2f; + mZoom = yZoom; + mYOffset = -getAbsoluteProjectTop() * mZoom; + mXOffset = -getAbsoluteProjectLeft() * mZoom + (this.getMeasuredWidth() - getAbsoluteProjectWidth() * mZoom) / 2f; } this.invalidate(); } @@ -835,19 +866,19 @@ private void adjustViewToProject() { // ********************************************************************************************** private float visibleX(float absoluteX) { - return mXOffset+mZoom*absoluteX; + return mXOffset + mZoom * absoluteX; } private float visibleY(float absoluteY) { - return mYOffset+mZoom*absoluteY; + return mYOffset + mZoom * absoluteY; } private float absoluteX(float visibleX) { - return (visibleX-mXOffset)/mZoom; + return (visibleX - mXOffset) / mZoom; } private float absoluteY(float visibleY) { - return (visibleY-mYOffset)/mZoom; + return (visibleY - mYOffset) / mZoom; } // ********************************************************************************************** @@ -856,7 +887,7 @@ private float absoluteY(float visibleY) { private UmlClass getTouchedClass(float visibleX, float visibleY) { - for (UmlClass c:mUmlProject.getUmlClasses()) { + for (UmlClass c : mUmlProject.getUmlClasses()) { if (c.containsPoint(absoluteX(visibleX), absoluteY(visibleY))) return c; } @@ -865,11 +896,11 @@ private UmlClass getTouchedClass(float visibleX, float visibleY) { public UmlRelation getTouchedRelation(float visibleX, float visibleY) { for (UmlRelation r : mUmlProject.getUmlRelations()) { - if (distance(absoluteX(visibleX),absoluteY(visibleY),r.getXOrigin(),r.getYOrigin(),r.getXEnd(),r.getYEnd())<=20 - && absoluteX(visibleX)>=Math.min(r.getXOrigin(),r.getXEnd())-20 - && absoluteX(visibleX)<=Math.max(r.getXOrigin(),r.getXEnd())+20 - && absoluteY(visibleY)>=Math.min(r.getYOrigin(),r.getYEnd())-20 - && absoluteY(visibleY)<=Math.max(r.getYOrigin(),r.getYEnd())+20) + if (distance(absoluteX(visibleX), absoluteY(visibleY), r.getXOrigin(), r.getYOrigin(), r.getXEnd(), r.getYEnd()) <= 20 + && absoluteX(visibleX) >= Math.min(r.getXOrigin(), r.getXEnd()) - 20 + && absoluteX(visibleX) <= Math.max(r.getXOrigin(), r.getXEnd()) + 20 + && absoluteY(visibleY) >= Math.min(r.getYOrigin(), r.getYEnd()) - 20 + && absoluteY(visibleY) <= Math.max(r.getYOrigin(), r.getYEnd()) + 20) return r; } return null; @@ -883,22 +914,22 @@ private float distance(float dotX, float dotY, float originX, float originY, flo float uY; if (originX == endX) { - uX=0; - uY=1; + uX = 0; + uY = 1; } else if (originY == endY) { uX = 1; uY = 0; } else { uX = (float) (1f / Math.sqrt(1f + (endX - originX) * (endX - originX) / (endY - originY) / (endY - originY))); - uY= (float) ((originX-endX)/(endY-originY)/Math.sqrt(1f + (endX - originX) * (endX - originX) / (endY - originY) / (endY - originY))); + uY = (float) ((originX - endX) / (endY - originY) / Math.sqrt(1f + (endX - originX) * (endX - originX) / (endY - originY) / (endY - originY))); } - return Math.abs((dotX-originX)*uX+(dotY-originY)*uY); + return Math.abs((dotX - originX) * uX + (dotY - originY) * uY); } private float distance(float X1, float Y1, float X2, float Y2) { //calculate the distance between two points M1(X1,Y1) and M2(X2,Y2) - return (float) Math.sqrt((X1-X2)*(X1-X2)+(Y1-Y2)*(Y1-Y2)); + return (float) Math.sqrt((X1 - X2) * (X1 - X2) + (Y1 - Y2) * (Y1 - Y2)); } private void updateProjectGeometricalParameters() { @@ -907,27 +938,17 @@ private void updateProjectGeometricalParameters() { mUmlProject.setYOffset(mYOffset); } -// ********************************************************************************************** + // ********************************************************************************************** // Interaction methods // ********************************************************************************************** private void promptDeleteRelation(final UmlRelation umlRelation, final View view) { - AlertDialog.Builder builder=new AlertDialog.Builder(getContext()); - builder.setTitle("Delete relation") + new MaterialAlertDialogBuilder(getContext()) + .setTitle("Delete relation") .setMessage("Are you sure you want to delete this relation ?") - .setNegativeButton("NO", new DialogInterface.OnClickListener() { - @Override - public void onClick(DialogInterface dialog, int which) { - - } - }) - .setPositiveButton("YES", new DialogInterface.OnClickListener() { - @Override - public void onClick(DialogInterface dialog, int which) { - mUmlProject.removeUmlRelation(umlRelation); - view.invalidate(); - } - }); - AlertDialog dialog=builder.create(); - dialog.show(); + .setNegativeButton("NO", (d, which) -> d.dismiss()) + .setPositiveButton("YES", (d, which) -> { + mUmlProject.removeUmlRelation(umlRelation); + view.invalidate(); + }).show(); } } diff --git a/app/src/main/java/com/nathaniel/motus/umlclasseditor/view/MethodEditorFragment.java b/app/src/main/java/com/nathaniel/motus/umlclasseditor/view/MethodEditorFragment.java index 5181c41..933068d 100644 --- a/app/src/main/java/com/nathaniel/motus/umlclasseditor/view/MethodEditorFragment.java +++ b/app/src/main/java/com/nathaniel/motus/umlclasseditor/view/MethodEditorFragment.java @@ -4,6 +4,7 @@ import android.content.DialogInterface; import android.os.Bundle; +import androidx.annotation.NonNull; import androidx.fragment.app.Fragment; import android.view.LayoutInflater; @@ -21,8 +22,10 @@ import android.widget.TextView; import android.widget.Toast; +import com.google.android.material.dialog.MaterialAlertDialogBuilder; import com.nathaniel.motus.umlclasseditor.R; import com.nathaniel.motus.umlclasseditor.controller.CustomExpandableListViewAdapter; +import com.nathaniel.motus.umlclasseditor.databinding.FragmentMethodEditorBinding; import com.nathaniel.motus.umlclasseditor.model.AdapterItem; import com.nathaniel.motus.umlclasseditor.model.AdapterItemComparator; import com.nathaniel.motus.umlclasseditor.model.AddItemString; @@ -38,6 +41,7 @@ import java.util.Collections; import java.util.HashMap; import java.util.List; +import java.util.Objects; /** * A simple {@link Fragment} subclass. @@ -48,7 +52,7 @@ public class MethodEditorFragment extends EditorFragment implements View.OnClick RadioGroup.OnCheckedChangeListener, AdapterView.OnItemLongClickListener, ExpandableListView.OnChildClickListener{ - + private FragmentMethodEditorBinding binding; private static final String METHOD_ORDER_KEY ="methodOrder"; private static final String CLASS_ORDER_KEY ="classOrder"; private static final String CLASS_EDITOR_FRAGMENT_TAG_KEY="classEditorFragmentTag"; @@ -57,22 +61,6 @@ public class MethodEditorFragment extends EditorFragment implements View.OnClick private UmlClassMethod mUmlClassMethod; private UmlClass mUmlClass; private String mClassEditorFragmentTag; - - private TextView mEditMethodText; - private Button mDeleteMethodButton; - private EditText mMethodNameEdit; - private RadioButton mPublicRadio; - private RadioButton mProtectedRadio; - private RadioButton mPrivateRadio; - private CheckBox mStaticCheck; - private Spinner mTypeSpinner; - private RadioGroup mMethodMultiplicityRadioGroup; - private RadioButton mSingleRadio; - private RadioButton mCollectionRadio; - private RadioButton mArrayRadio; - private TextView mDimText; - private EditText mDimEdit; - private ExpandableListView mParameterList; private Button mCancelButton; private Button mOKButton; @@ -104,10 +92,11 @@ public static MethodEditorFragment newInstance(String classEditorFragmentTag, in // ********************************************************************************************** @Override - public View onCreateView(LayoutInflater inflater, ViewGroup container, + public View onCreateView(@NonNull LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { // Inflate the layout for this fragment - return inflater.inflate(R.layout.fragment_method_editor, container, false); + binding = FragmentMethodEditorBinding.inflate(inflater,container,false); + return binding.getRoot(); } // ********************************************************************************************** @@ -130,48 +119,24 @@ protected void setOnCreateOrEditDisplay() { } protected void configureViews() { - mEditMethodText=getActivity().findViewById(R.id.edit_method_text); - - mDeleteMethodButton=getActivity().findViewById(R.id.delete_method_button); - mDeleteMethodButton.setOnClickListener(this); - mDeleteMethodButton.setTag(DELETE_METHOD_BUTTON_TAG); - - mMethodNameEdit=getActivity().findViewById(R.id.method_name_input); - - mPublicRadio=getActivity().findViewById(R.id.method_public_radio); - - mProtectedRadio=getActivity().findViewById(R.id.method_protected_radio); - - mPrivateRadio=getActivity().findViewById(R.id.method_private_radio); - - mStaticCheck=getActivity().findViewById(R.id.method_static_check); - - mTypeSpinner=getActivity().findViewById(R.id.method_type_spinner); + // delete btn + binding.deleteMethodButton.setOnClickListener(this); + binding.deleteMethodButton.setTag(DELETE_METHOD_BUTTON_TAG); - mMethodMultiplicityRadioGroup=getActivity().findViewById(R.id.method_multiplicity_radio_group); - mMethodMultiplicityRadioGroup.setOnCheckedChangeListener(this); + // method type single =void, collection = list, array = array + binding.methodMultiplicityRadioGroup.setOnCheckedChangeListener(this); - mSingleRadio=getActivity().findViewById(R.id.method_simple_radio); + // parameters expanded list view + binding.methodParametersList.setOnChildClickListener(this); + binding.methodParametersList.setOnItemLongClickListener(this); - mCollectionRadio=getActivity().findViewById(R.id.method_collection_radio); + // cancel btn + binding.methodCancelButton.setOnClickListener(this); + binding.methodCancelButton.setTag(CANCEL_BUTTON_TAG); - mArrayRadio=getActivity().findViewById(R.id.method_array_radio); - - mDimText=getActivity().findViewById(R.id.method_dimension_text); - - mDimEdit=getActivity().findViewById(R.id.method_dimension_input); - - mParameterList=getActivity().findViewById(R.id.method_parameters_list); - mParameterList.setOnChildClickListener(this); - mParameterList.setOnItemLongClickListener(this); - - mCancelButton=getActivity().findViewById(R.id.method_cancel_button); - mCancelButton.setOnClickListener(this); - mCancelButton.setTag(CANCEL_BUTTON_TAG); - - mOKButton=getActivity().findViewById(R.id.method_ok_button); - mOKButton.setOnClickListener(this); - mOKButton.setTag(OK_BUTTON_TAG); + // ok btn + binding.methodOkButton.setOnClickListener(this); + binding.methodOkButton.setTag(OK_BUTTON_TAG); } protected void initializeMembers() { @@ -187,44 +152,44 @@ protected void initializeMembers() { protected void initializeFields() { if (mMethodOrder != -1) { - mMethodNameEdit.setText(mUmlClassMethod.getName()); + binding.methodNameInput.setText(mUmlClassMethod.getName()); switch (mUmlClassMethod.getVisibility()) { case PUBLIC: - mPublicRadio.setChecked(true); + binding.methodPublicRadio.setChecked(true); break; case PROTECTED: - mProtectedRadio.setChecked(true); + binding.methodProtectedRadio.setChecked(true); break; default: - mPrivateRadio.setChecked(true); + binding.methodPrivateRadio.setChecked(true); break; } - mStaticCheck.setChecked(mUmlClassMethod.isStatic()); + binding.methodStaticCheck.setChecked(mUmlClassMethod.isStatic()); switch (mUmlClassMethod.getTypeMultiplicity()) { case SINGLE: - mSingleRadio.setChecked(true); + binding.methodSimpleRadio.setChecked(true); break; case COLLECTION: - mCollectionRadio.setChecked(true); + binding.methodCollectionRadio.setChecked(true); break; default: - mArrayRadio.setChecked(true); + binding.methodArrayRadio.setChecked(true); break; } - mDimEdit.setText(Integer.toString(mUmlClassMethod.getArrayDimension())); + binding.methodDimensionInput.setText(Integer.toString(mUmlClassMethod.getArrayDimension())); if (mUmlClassMethod.getTypeMultiplicity() == TypeMultiplicity.ARRAY) setOnArrayDisplay(); else setOnSingleDisplay(); } else { - mMethodNameEdit.setText(""); - mPublicRadio.setChecked(true); - mStaticCheck.setChecked(false); - mSingleRadio.setChecked(true); - mDimEdit.setText(""); + binding.methodNameInput.setText(""); + binding.methodPublicRadio.setChecked(true); + binding.methodStaticCheck.setChecked(false); + binding.methodSimpleRadio.setChecked(true); + binding.methodDimensionInput.setText(""); setOnSingleDisplay(); } populateTypeSpinner(); @@ -238,15 +203,16 @@ private void populateTypeSpinner() { Collections.sort(spinnerArray,new TypeNameComparator()); ArrayAdapter adapter=new ArrayAdapter<>(getContext(),android.R.layout.simple_spinner_item,spinnerArray); adapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item); - mTypeSpinner.setAdapter(adapter); + binding.methodTypeSpinner.setAdapter(adapter); if (mMethodOrder !=-1) - mTypeSpinner.setSelection(spinnerArray.indexOf(mUmlClassMethod.getUmlType().getName())); - else mTypeSpinner.setSelection(spinnerArray.indexOf("void")); + binding.methodTypeSpinner.setSelection(spinnerArray.indexOf(mUmlClassMethod.getUmlType().getName())); + else binding.methodTypeSpinner.setSelection(spinnerArray.indexOf("void")); } private void populateParameterListView() { boolean parameterGroupIsExpanded=false; - if (mParameterList.getExpandableListAdapter()!=null && mParameterList.isGroupExpanded(0)) + ExpandableListView paramList = binding.methodParametersList; + if (paramList.getExpandableListAdapter()!=null && paramList.isGroupExpanded(0)) parameterGroupIsExpanded=true; List parameterList=new ArrayList<>(); @@ -262,29 +228,29 @@ private void populateParameterListView() { title.add(getString(R.string.parameters_string)); CustomExpandableListViewAdapter adapter=new CustomExpandableListViewAdapter(getContext(),title,hashMap); - mParameterList.setAdapter(adapter); + paramList.setAdapter(adapter); if (parameterGroupIsExpanded) - mParameterList.expandGroup(0); + paramList.expandGroup(0); } private void setOnEditDisplay() { - mEditMethodText.setText("Edit method"); - mDeleteMethodButton.setVisibility(View.VISIBLE); + binding.editMethodText.setText("Edit Method"); + binding.deleteMethodButton.setVisibility(View.VISIBLE); } private void setOnCreateDisplay() { - mEditMethodText.setText("Create method"); - mDeleteMethodButton.setVisibility(View.INVISIBLE); + binding.editMethodText.setText("Create method"); + binding.deleteMethodButton.setVisibility(View.INVISIBLE); } private void setOnArrayDisplay() { - mDimText.setVisibility(View.VISIBLE); - mDimEdit.setVisibility(View.VISIBLE); + binding.methodDimensionText.setVisibility(View.VISIBLE); + binding.methodDimensionInput.setVisibility(View.VISIBLE); } private void setOnSingleDisplay() { - mDimText.setVisibility(View.INVISIBLE); - mDimEdit.setVisibility(View.INVISIBLE); + binding.methodDimensionText.setVisibility(View.INVISIBLE); + binding.methodDimensionInput.setVisibility(View.INVISIBLE); } public void updateMethodEditorFragment(int methodOrder,int classOrder) { @@ -396,32 +362,32 @@ private boolean createOrUpdateMethod() { } private String getMethodName() { - return mMethodNameEdit.getText().toString(); + return Objects.requireNonNull(binding.methodNameInput.getText()).toString(); } private Visibility getMethodVisibility() { - if (mPublicRadio.isChecked()) return Visibility.PUBLIC; - if (mPrivateRadio.isChecked()) return Visibility.PROTECTED; + if (binding.methodPublicRadio.isChecked()) return Visibility.PUBLIC; + if (binding.methodPrivateRadio.isChecked()) return Visibility.PROTECTED; return Visibility.PRIVATE; } private boolean isStatic() { - return mStaticCheck.isChecked(); + return binding.methodStaticCheck.isChecked(); } private UmlType getMethodType() { - return UmlType.valueOf(mTypeSpinner.getSelectedItem().toString(),UmlType.getUmlTypes()); + return UmlType.valueOf(binding.methodTypeSpinner.getSelectedItem().toString(),UmlType.getUmlTypes()); } private TypeMultiplicity getMethodMultiplicity() { - if (mSingleRadio.isChecked()) return TypeMultiplicity.SINGLE; - if (mCollectionRadio.isChecked()) return TypeMultiplicity.COLLECTION; + if (binding.methodSimpleRadio.isChecked()) return TypeMultiplicity.SINGLE; + if (binding.methodCollectionRadio.isChecked()) return TypeMultiplicity.COLLECTION; return TypeMultiplicity.ARRAY; } private int getArrayDimension() { - if (mDimEdit.getText().toString().equals("")) return 0; - return Integer.parseInt(mDimEdit.getText().toString()); + if (binding.methodDimensionInput.getText().toString().equals("")) return 0; + return Integer.parseInt(binding.methodDimensionInput.getText().toString()); } public void updateLists() { @@ -433,44 +399,25 @@ public void updateLists() { // ********************************************************************************************** private void startDeleteMethodDialog() { final Fragment fragment=this; - AlertDialog.Builder builder=new AlertDialog.Builder(getContext()); - builder.setTitle("Delete method ?") + new MaterialAlertDialogBuilder(requireContext()) + .setTitle("Delete method ?") .setMessage("Are you sure you want to delete this method ?") - .setNegativeButton("NO", new DialogInterface.OnClickListener() { - @Override - public void onClick(DialogInterface dialog, int which) { - - } - }) - .setPositiveButton("YES", new DialogInterface.OnClickListener() { - @Override - public void onClick(DialogInterface dialog, int which) { - mUmlClass.removeMethod(mUmlClassMethod); - mCallback.closeMethodEditorFragment(fragment); - } - }); - AlertDialog dialog=builder.create(); - dialog.show(); + .setNegativeButton("NO", (d, which) -> d.dismiss()) + .setPositiveButton("YES", (d, which) -> { + mUmlClass.removeMethod(mUmlClassMethod); + mCallback.closeMethodEditorFragment(fragment); + }).show(); } private void startDeleteParameterDialog(final int parameterIndex) { - AlertDialog.Builder builder=new AlertDialog.Builder(getContext()); - builder.setTitle("Delete parameter ?") + new MaterialAlertDialogBuilder(requireContext()) + .setTitle("Delete parameter ?") .setMessage("Are you sure you want delete this parameter ?") - .setNegativeButton("NO", new DialogInterface.OnClickListener() { - @Override - public void onClick(DialogInterface dialogInterface, int i) { - - } - }) - .setPositiveButton("YES", new DialogInterface.OnClickListener() { - @Override - public void onClick(DialogInterface dialogInterface, int i) { - mUmlClassMethod.removeParameter(mUmlClassMethod.findParameterByOrder(parameterIndex)); - updateLists(); - } + .setNegativeButton("NO", (d, i) -> d.dismiss()) + .setPositiveButton("YES", (d, i) -> { + mUmlClassMethod.removeParameter(mUmlClassMethod.findParameterByOrder(parameterIndex)); + updateLists(); }) - .create() .show(); } } \ No newline at end of file diff --git a/app/src/main/java/com/nathaniel/motus/umlclasseditor/view/ParameterEditorFragment.java b/app/src/main/java/com/nathaniel/motus/umlclasseditor/view/ParameterEditorFragment.java index 480ef0b..194beee 100644 --- a/app/src/main/java/com/nathaniel/motus/umlclasseditor/view/ParameterEditorFragment.java +++ b/app/src/main/java/com/nathaniel/motus/umlclasseditor/view/ParameterEditorFragment.java @@ -18,7 +18,9 @@ import android.widget.TextView; import android.widget.Toast; +import com.google.android.material.dialog.MaterialAlertDialogBuilder; import com.nathaniel.motus.umlclasseditor.R; +import com.nathaniel.motus.umlclasseditor.databinding.FragmentParameterEditorBinding; import com.nathaniel.motus.umlclasseditor.model.MethodParameter; import com.nathaniel.motus.umlclasseditor.model.TypeMultiplicity; import com.nathaniel.motus.umlclasseditor.model.TypeNameComparator; @@ -29,6 +31,7 @@ import java.util.ArrayList; import java.util.Collections; import java.util.List; +import java.util.Objects; /** * A simple {@link Fragment} subclass. @@ -36,7 +39,7 @@ * create an instance of this fragment. */ public class ParameterEditorFragment extends EditorFragment implements View.OnClickListener, RadioGroup.OnCheckedChangeListener { - + private FragmentParameterEditorBinding binding; private static final String PARAMETER_ORDER_KEY ="parameterOrder"; private static final String METHOD_ORDER_KEY ="methodOrder"; private static final String CLASS_ORDER_KEY ="classOrder"; @@ -49,19 +52,6 @@ public class ParameterEditorFragment extends EditorFragment implements View.OnCl private UmlClassMethod mUmlClassMethod; private UmlClass mUmlClass; - private TextView mEditParameterText; - private Button mDeleteParameterButton; - private EditText mParameterNameEdit; - private Spinner mParameterTypeSpinner; - private RadioGroup mParameterMultiplicityRadioGroup; - private RadioButton mSingleRadio; - private RadioButton mCollectionRadio; - private RadioButton mArrayRadio; - private TextView mDimText; - private EditText mDimEdit; - private Button mCancelButton; - private Button mOKButton; - private static final int DELETE_PARAMETER_BUTTON_TAG=510; private static final int CANCEL_BUTTON_TAG=520; private static final int OK_BUTTON_TAG=530; @@ -89,7 +79,8 @@ public static ParameterEditorFragment newInstance(String methodEditorFragmentTag public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { // Inflate the layout for this fragment - return inflater.inflate(R.layout.fragment_parameter_editor, container, false); + binding = FragmentParameterEditorBinding.inflate(inflater,container,false); + return binding.getRoot(); } // ********************************************************************************************** @@ -157,55 +148,39 @@ protected void initializeMembers() { } protected void configureViews() { - mEditParameterText=getActivity().findViewById(R.id.edit_parameter_text); - - mDeleteParameterButton=getActivity().findViewById(R.id.delete_parameter_button); - mDeleteParameterButton.setTag(DELETE_PARAMETER_BUTTON_TAG); - mDeleteParameterButton.setOnClickListener(this); - - mParameterNameEdit=getActivity().findViewById(R.id.parameter_name_input); - - mParameterTypeSpinner=getActivity().findViewById(R.id.parameter_type_spinner); - - mParameterMultiplicityRadioGroup=getActivity().findViewById(R.id.parameter_multiplicity_radio_group); - mParameterMultiplicityRadioGroup.setOnCheckedChangeListener(this); - - mSingleRadio=getActivity().findViewById(R.id.parameter_simple_radio); - - mCollectionRadio=getActivity().findViewById(R.id.parameter_collection_radio); - - mArrayRadio=getActivity().findViewById(R.id.parameter_array_radio); - - mDimText=getActivity().findViewById(R.id.parameter_dimension_text); + // delete btn + binding.deleteParameterButton.setOnClickListener(this); + binding.deleteParameterButton.setTag(DELETE_PARAMETER_BUTTON_TAG); - mDimEdit=getActivity().findViewById(R.id.parameter_dimension_input); + // param type single =void, collection = list, array = array + binding.parameterMultiplicityRadioGroup.setOnCheckedChangeListener(this); - mCancelButton=getActivity().findViewById(R.id.parameter_cancel_button); - mCancelButton.setTag(CANCEL_BUTTON_TAG); - mCancelButton.setOnClickListener(this); + // cancel btn + binding.parameterCancelButton.setTag(CANCEL_BUTTON_TAG); + binding.parameterCancelButton.setOnClickListener(this); - mOKButton=getActivity().findViewById(R.id.parameter_ok_button); - mOKButton.setTag(OK_BUTTON_TAG); - mOKButton.setOnClickListener(this); + // ok btn + binding.parameterOkButton.setTag(OK_BUTTON_TAG); + binding.parameterOkButton.setOnClickListener(this); } protected void initializeFields() { if (mParameterOrder != -1) { - mParameterNameEdit.setText(mMethodParameter.getName()); + binding.parameterNameInput.setText(mMethodParameter.getName()); if (mMethodParameter.getTypeMultiplicity() == TypeMultiplicity.SINGLE) - mSingleRadio.setChecked(true); + binding.parameterSimpleRadio.setChecked(true); if (mMethodParameter.getTypeMultiplicity() == TypeMultiplicity.COLLECTION) - mCollectionRadio.setChecked(true); + binding.parameterCollectionRadio.setChecked(true); if (mMethodParameter.getTypeMultiplicity() == TypeMultiplicity.ARRAY) - mArrayRadio.setChecked(true); - mDimEdit.setText(Integer.toString(mMethodParameter.getArrayDimension())); + binding.parameterArrayRadio.setChecked(true); + binding.parameterDimensionInput.setText(Integer.toString(mMethodParameter.getArrayDimension())); if (mMethodParameter.getTypeMultiplicity() == TypeMultiplicity.ARRAY) setOnArrayDisplay(); else setOnSingleDisplay(); } else { - mParameterNameEdit.setText(""); - mSingleRadio.setChecked(true); - mDimEdit.setText(""); + binding.parameterNameInput.setText(""); + binding.parameterSimpleRadio.setChecked(true); + binding.parameterDimensionInput.setText(""); setOnSingleDisplay(); } populateTypeSpinner(); @@ -218,29 +193,29 @@ private void populateTypeSpinner() { Collections.sort(arrayList,new TypeNameComparator()); ArrayAdapter adapter=new ArrayAdapter<>(getContext(),android.R.layout.simple_spinner_item,arrayList); adapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item); - mParameterTypeSpinner.setAdapter(adapter); + binding.parameterTypeSpinner.setAdapter(adapter); if (mParameterOrder !=-1) - mParameterTypeSpinner.setSelection(arrayList.indexOf(mMethodParameter.getUmlType().getName())); + binding.parameterTypeSpinner.setSelection(arrayList.indexOf(mMethodParameter.getUmlType().getName())); } private void setOnEditDisplay(){ - mEditParameterText.setText("Edit parameter"); - mDeleteParameterButton.setVisibility(View.VISIBLE); + binding.editParameterText.setText("Edit parameter"); + binding.deleteParameterButton.setVisibility(View.VISIBLE); } private void setOnCreateDisplay() { - mEditParameterText.setText("Create parameter"); - mDeleteParameterButton.setVisibility(View.INVISIBLE); + binding.editParameterText.setText("Create parameter"); + binding.deleteParameterButton.setVisibility(View.INVISIBLE); } private void setOnSingleDisplay() { - mDimText.setVisibility(View.INVISIBLE); - mDimEdit.setVisibility(View.INVISIBLE); + binding.parameterDimensionText.setVisibility(View.INVISIBLE); + binding.parameterDimensionInput.setVisibility(View.INVISIBLE); } private void setOnArrayDisplay() { - mDimText.setVisibility(View.VISIBLE); - mDimEdit.setVisibility(View.VISIBLE); + binding.parameterDimensionText.setVisibility(View.VISIBLE); + binding.parameterDimensionInput.setVisibility(View.VISIBLE); } public void updateParameterEditorFragment(int parameterOrder,int methodOrder,int classOrder) { @@ -295,22 +270,22 @@ private boolean createOrUpdateParameter() { } private String getParameterName() { - return mParameterNameEdit.getText().toString(); + return Objects.requireNonNull(binding.parameterNameInput.getText()).toString(); } private UmlType getParameterType() { - return UmlType.valueOf(mParameterTypeSpinner.getSelectedItem().toString(),UmlType.getUmlTypes()); + return UmlType.valueOf(binding.parameterTypeSpinner.getSelectedItem().toString(),UmlType.getUmlTypes()); } private TypeMultiplicity getParameterMultiplicity() { - if (mSingleRadio.isChecked()) return TypeMultiplicity.SINGLE; - if (mCollectionRadio.isChecked()) return TypeMultiplicity.COLLECTION; + if (binding.parameterSimpleRadio.isChecked()) return TypeMultiplicity.SINGLE; + if (binding.parameterCollectionRadio.isChecked()) return TypeMultiplicity.COLLECTION; return TypeMultiplicity.ARRAY; } private int getArrayDimension() { - if (mDimEdit.getText().toString().equals("")) return 0; - return Integer.parseInt(mDimEdit.getText().toString()); + if (binding.parameterDimensionInput.getText().toString().equals("")) return 0; + return Integer.parseInt(binding.parameterDimensionInput.getText().toString()); } // ********************************************************************************************** @@ -318,24 +293,14 @@ private int getArrayDimension() { // ********************************************************************************************** private void startDeleteParameterDialog() { final Fragment fragment=this; - AlertDialog.Builder builder=new AlertDialog.Builder(getContext()); - builder.setTitle("Delete Parameter") + new MaterialAlertDialogBuilder(requireContext()) + .setTitle("Delete Parameter") .setMessage("Are you sure you to delete this parameter ?") - .setNegativeButton("NO", new DialogInterface.OnClickListener() { - @Override - public void onClick(DialogInterface dialog, int which) { - - } - }) - .setPositiveButton("YES", new DialogInterface.OnClickListener() { - @Override - public void onClick(DialogInterface dialog, int which) { - mUmlClassMethod.removeParameter(mMethodParameter); - mCallback.closeParameterEditorFragment(fragment); - } - }); - AlertDialog dialog=builder.create(); - dialog.show(); + .setNegativeButton("NO", (DialogInterface.OnClickListener) (d, which) -> d.dismiss()) + .setPositiveButton("YES", (DialogInterface.OnClickListener) (d, which) -> { + mUmlClassMethod.removeParameter(mMethodParameter); + mCallback.closeParameterEditorFragment(fragment); + }).show(); } } \ No newline at end of file diff --git a/app/src/main/res/drawable/ic_add.xml b/app/src/main/res/drawable/ic_add.xml new file mode 100644 index 0000000..89633bb --- /dev/null +++ b/app/src/main/res/drawable/ic_add.xml @@ -0,0 +1,5 @@ + + + diff --git a/app/src/main/res/drawable/ic_cancel.xml b/app/src/main/res/drawable/ic_cancel.xml new file mode 100644 index 0000000..a0a94e3 --- /dev/null +++ b/app/src/main/res/drawable/ic_cancel.xml @@ -0,0 +1,5 @@ + + + diff --git a/app/src/main/res/drawable/ic_check.xml b/app/src/main/res/drawable/ic_check.xml new file mode 100644 index 0000000..cf143d4 --- /dev/null +++ b/app/src/main/res/drawable/ic_check.xml @@ -0,0 +1,5 @@ + + + diff --git a/app/src/main/res/drawable/ic_create_new_folder.xml b/app/src/main/res/drawable/ic_create_new_folder.xml new file mode 100644 index 0000000..a0bb1a6 --- /dev/null +++ b/app/src/main/res/drawable/ic_create_new_folder.xml @@ -0,0 +1,5 @@ + + + diff --git a/app/src/main/res/drawable/ic_delete.xml b/app/src/main/res/drawable/ic_delete.xml new file mode 100644 index 0000000..a0c03a9 --- /dev/null +++ b/app/src/main/res/drawable/ic_delete.xml @@ -0,0 +1,5 @@ + + + diff --git a/app/src/main/res/drawable/ic_export.xml b/app/src/main/res/drawable/ic_export.xml new file mode 100644 index 0000000..9341558 --- /dev/null +++ b/app/src/main/res/drawable/ic_export.xml @@ -0,0 +1,5 @@ + + + diff --git a/app/src/main/res/drawable/ic_folder_copy.xml b/app/src/main/res/drawable/ic_folder_copy.xml new file mode 100644 index 0000000..c30565e --- /dev/null +++ b/app/src/main/res/drawable/ic_folder_copy.xml @@ -0,0 +1,6 @@ + + + + diff --git a/app/src/main/res/drawable/ic_help.xml b/app/src/main/res/drawable/ic_help.xml new file mode 100644 index 0000000..0028ebd --- /dev/null +++ b/app/src/main/res/drawable/ic_help.xml @@ -0,0 +1,5 @@ + + + diff --git a/app/src/main/res/drawable/ic_import.xml b/app/src/main/res/drawable/ic_import.xml new file mode 100644 index 0000000..a4ab511 --- /dev/null +++ b/app/src/main/res/drawable/ic_import.xml @@ -0,0 +1,5 @@ + + + diff --git a/app/src/main/res/drawable/ic_merge.xml b/app/src/main/res/drawable/ic_merge.xml new file mode 100644 index 0000000..f41d9c7 --- /dev/null +++ b/app/src/main/res/drawable/ic_merge.xml @@ -0,0 +1,5 @@ + + + diff --git a/app/src/main/res/drawable/ic_save.xml b/app/src/main/res/drawable/ic_save.xml new file mode 100644 index 0000000..82070aa --- /dev/null +++ b/app/src/main/res/drawable/ic_save.xml @@ -0,0 +1,5 @@ + + + diff --git a/app/src/main/res/drawable/new_class_locate_layout.xml b/app/src/main/res/drawable/new_class_locate_layout.xml new file mode 100644 index 0000000..26a6da8 --- /dev/null +++ b/app/src/main/res/drawable/new_class_locate_layout.xml @@ -0,0 +1,9 @@ + + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/activity_crash.xml b/app/src/main/res/layout/activity_crash.xml new file mode 100644 index 0000000..21f889d --- /dev/null +++ b/app/src/main/res/layout/activity_crash.xml @@ -0,0 +1,49 @@ + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/activity_main.xml b/app/src/main/res/layout/activity_main.xml index 7055a8e..d0f4bb7 100644 --- a/app/src/main/res/layout/activity_main.xml +++ b/app/src/main/res/layout/activity_main.xml @@ -5,13 +5,18 @@ android:layout_height="match_parent" xmlns:app="http://schemas.android.com/apk/res-auto" android:orientation="vertical"> - - + android:layout_height="wrap_content"> + + + + - - - - - - - - - - + + - + + - + + + + + + - - - - - - - - - - - - + + + + + + + + + - + + - + + + + - + android:layout_toRightOf="@id/attribute_type_text" /> - - - - - -