Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Icon Manager #427

Open
wants to merge 38 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
38 commits
Select commit Hold shift + click to select a range
6a09621
feat: added svg parser library for iconmanager
lazy-pr0grammer May 8, 2022
2176d99
feat: added icon_manager_fragment
lazy-pr0grammer May 8, 2022
9e0537f
feat: added icon_manager_item
lazy-pr0grammer May 8, 2022
823ebc9
feat: added create_vector_dialog
lazy-pr0grammer May 8, 2022
7661457
feat: added outline_sync_24
lazy-pr0grammer May 8, 2022
14ffc2e
feat: added iconmanagerfragment
lazy-pr0grammer May 8, 2022
9e3ecdf
Rename app/src/main/java/com/tyron/code/ui/IconManagerFragment.java t…
lazy-pr0grammer May 8, 2022
9ecb716
feat: added iconmanageradapter
lazy-pr0grammer May 8, 2022
0127b52
feat: added editvectordialogfragment
lazy-pr0grammer May 8, 2022
554f57b
feat: added openiconmanageraction
lazy-pr0grammer May 8, 2022
04e1bb4
feat: added openIconManagerAction
lazy-pr0grammer May 8, 2022
c02a6af
feat: added iconmanager string
lazy-pr0grammer May 8, 2022
cf5976f
feat: added iconmanager menu
lazy-pr0grammer May 8, 2022
fba4d3c
fix: solved compile related errors
lazy-pr0grammer May 8, 2022
3edaea4
fix: compile related errors
lazy-pr0grammer May 8, 2022
bf948bb
feat: added confirmation dialog while extracting files
lazy-pr0grammer May 8, 2022
cc5c92c
feat: fixed some compile related issues
lazy-pr0grammer May 8, 2022
bd231e6
feat: added icons.zip(conatains 5000+ icons)
lazy-pr0grammer May 8, 2022
ea9f86f
fix: fixed compile related errors
lazy-pr0grammer May 8, 2022
e85f738
fix: fixed compile related errors
lazy-pr0grammer May 8, 2022
cf62eca
fix: fixed compile related issues
lazy-pr0grammer May 8, 2022
c63531b
fix: removed compile related errors
lazy-pr0grammer May 8, 2022
13698f8
fix: compile related errors
lazy-pr0grammer May 8, 2022
2f89e9a
fix: compile related errors
lazy-pr0grammer May 8, 2022
3293792
fix: compile related errors
lazy-pr0grammer May 8, 2022
edb5cde
fix: compile related errors
lazy-pr0grammer May 8, 2022
66e9831
fix: fragment not attached to a context
lazy-pr0grammer May 8, 2022
f91fdb0
fix: calledfromwrongthreadexception
lazy-pr0grammer May 8, 2022
0b87e35
refactor: removed unwanted spaces, code cleanup
lazy-pr0grammer May 8, 2022
7265b05
refactor: removed unwanted spaces and code cleanup
lazy-pr0grammer May 8, 2022
97fc5e2
fix: box doesnt shows full text
lazy-pr0grammer May 8, 2022
f63ce25
feat: added uiutilskt
lazy-pr0grammer May 8, 2022
d794e39
fix: icon got copied to wrong folder
lazy-pr0grammer May 8, 2022
8d66e9a
fix: added missing imports
lazy-pr0grammer May 8, 2022
bdff555
fix: dialog crashed
lazy-pr0grammer May 8, 2022
133a0fd
Merge branch 'main' into main
lazy-pr0grammer May 17, 2022
d72b513
Merge branch 'tyron12233:main' into main
lazy-pr0grammer Jun 9, 2022
23cba04
Merge branch 'tyron12233:main' into main
lazy-pr0grammer Jun 18, 2022
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions app/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -74,6 +74,7 @@ dependencies {
// TODO: completion providers should not be included on the main module
// alternate editor impl
implementation 'com.blacksquircle.ui:editorkit:2.1.2'
implementation 'com.caverock:androidsvg-aar:1.4'

implementation project(path: ':code-editor')
implementation project(path: ':xml-completion')
Expand Down
Binary file added app/src/main/assets/Icons.zip
Binary file not shown.
4 changes: 3 additions & 1 deletion app/src/main/java/com/tyron/code/ApplicationLoader.java
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@
import com.tyron.code.ui.main.action.debug.DebugActionGroup;
import com.tyron.code.ui.main.action.other.FormatAction;
import com.tyron.code.ui.main.action.other.OpenSettingsAction;
import com.tyron.code.ui.main.action.other.OpenIconManagerAction;
import com.tyron.code.ui.main.action.project.ProjectActionGroup;
import com.tyron.code.ui.settings.ApplicationSettingsFragment;
import com.tyron.common.ApplicationProvider;
Expand Down Expand Up @@ -145,6 +146,7 @@ private void runStartup() {
manager.registerAction(CompileActionGroup.ID, new CompileActionGroup());
manager.registerAction(ProjectActionGroup.ID, new ProjectActionGroup());
manager.registerAction(PreviewLayoutAction.ID, new PreviewLayoutAction());
manager.registerAction(OpenIconManagerAction.ID, new OpenIconManagerAction());
manager.registerAction(OpenSettingsAction.ID, new OpenSettingsAction());
manager.registerAction(FormatAction.ID, new FormatAction());
manager.registerAction(DebugActionGroup.ID, new DebugActionGroup());
Expand Down Expand Up @@ -190,4 +192,4 @@ public static void showToast(String message) {
public static void setApplicationContext(Context context) {
applicationContext = context;
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,197 @@
package com.tyron.code.ui.iconmanager;

import android.graphics.PorterDuff;
import android.graphics.Color;
import android.graphics.drawable.Drawable;
import android.graphics.drawable.PictureDrawable;

import android.text.Editable;
import android.view.View;
import android.os.Bundle;
import android.app.Dialog;

import android.widget.EditText;
import android.widget.ImageView;
import android.widget.Button;
import android.widget.LinearLayout;
import android.widget.Toast;

import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.appcompat.app.AlertDialog;

import com.caverock.androidsvg.SVG;

import com.google.android.material.dialog.MaterialAlertDialogBuilder;
import androidx.fragment.app.DialogFragment;
import com.google.android.material.textfield.TextInputEditText;
import com.google.android.material.textfield.TextInputLayout;

import com.tyron.code.R;
import com.tyron.code.ui.project.ProjectManager;
import com.tyron.common.util.SingleTextWatcher;

import java.io.File;
import java.io.FileInputStream;
import java.nio.charset.StandardCharsets;
import java.nio.file.Files;
import java.nio.file.Paths;
import java.nio.file.StandardOpenOption;

import org.w3c.dom.Element;
import org.w3c.dom.NodeList;
import org.w3c.dom.Document;

import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;

public class EditVectorDialogFragment extends DialogFragment {

public static final String TAG = EditVectorDialogFragment.class.getSimpleName();
public static final String ADD_KEY = "addVector";
private String iconPath, projectResourceDirectory;

@SuppressWarnings("ConstantConditions")
@NonNull
@Override
public Dialog onCreateDialog(@Nullable Bundle savedInstanceState) {

Bundle bundle = this.getArguments();
if (bundle != null) {
iconPath = bundle.getString("iconPath");
projectResourceDirectory = ProjectManager.getInstance().getCurrentProject().getRootFile().getAbsolutePath() + "/app/src/main/res/drawable/";
}

MaterialAlertDialogBuilder builder = new MaterialAlertDialogBuilder(requireContext());
View inflate = getLayoutInflater().inflate(R.layout.create_vector_dialog, null);
TextInputLayout textinput1 = (TextInputLayout) inflate.findViewById(R.id.textinputlayout1);
TextInputLayout textinput2 = (TextInputLayout) inflate.findViewById(R.id.textinputlayout2);
TextInputLayout textinput3 = (TextInputLayout) inflate.findViewById(R.id.textinputlayout3);
TextInputLayout textinput4 = (TextInputLayout) inflate.findViewById(R.id.textinputlayout4);
TextInputLayout textinput5 = (TextInputLayout) inflate.findViewById(R.id.textinputlayout5);
TextInputEditText name = (TextInputEditText) inflate.findViewById(R.id.name);
TextInputEditText height = (TextInputEditText) inflate.findViewById(R.id.height);
TextInputEditText width = (TextInputEditText) inflate.findViewById(R.id.width);
TextInputEditText color = (TextInputEditText) inflate.findViewById(R.id.color);
TextInputEditText path = (TextInputEditText) inflate.findViewById(R.id.path);
ImageView icon = (ImageView) inflate.findViewById(R.id.icon);
LinearLayout container = (LinearLayout) inflate.findViewById(R.id.container);
LinearLayout round = (LinearLayout) inflate.findViewById(R.id.round);

round.setBackgroundColor(0XFF000000);
path.setEnabled(false);
path.setText(projectResourceDirectory);

textinput4.setEndIconOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
if (!color.getText().toString().trim().startsWith("#")) {
Toast.makeText(requireContext(), "Invalid color code", 3000).show();
} else {
try {
icon.setColorFilter(Color.parseColor(color.getText().toString().trim()), PorterDuff.Mode.MULTIPLY);
round.setBackgroundColor(Color.parseColor(color.getText().toString().trim()));
} catch (Exception e) {
Toast.makeText(requireContext(), e.toString(), 3000).show();
}
}
}
});

builder.setView(inflate);

if (iconPath.contains(".svg")) {
name.setText(new File(iconPath).getName().replace(".svg", ""));
} else if (iconPath.contains(".xml")) {
name.setText(new File(iconPath).getName().replace(".xml", ""));
}

icon.setImageDrawable(loadSvg(iconPath));

builder.setPositiveButton("Create", (d, w) -> {
generateSvg2Vector(name.getText().toString().trim(), width.getText().toString().trim(), height.getText().toString().trim(), color.getText().toString().trim(), iconPath, projectResourceDirectory);
});

builder.setNegativeButton("Cancel", null);

AlertDialog dialog = builder.create();
dialog.setOnShowListener(d -> {
final Button positiveButton = dialog.getButton(AlertDialog.BUTTON_POSITIVE);
SingleTextWatcher textWatcher = new SingleTextWatcher() {
@Override
public void afterTextChanged(Editable editable) {
boolean valid = validate(name, height, width, color, path);
positiveButton.setEnabled(valid);
}
};

name.addTextChangedListener(textWatcher);
height.addTextChangedListener(textWatcher);
width.addTextChangedListener(textWatcher);
color.addTextChangedListener(textWatcher);
path.addTextChangedListener(textWatcher);
});

return dialog;
}

private void generateSvg2Vector(String name, String width, String height, String color, String source, String destination) {

File svgPath = new File(source);
DocumentBuilderFactory documentBuilderFactory = DocumentBuilderFactory.newInstance();

try {
DocumentBuilder documentBuilder = documentBuilderFactory.newDocumentBuilder();
Document document = documentBuilder.parse(svgPath);
NodeList nodeList = document.getElementsByTagName("path");
if (nodeList.getLength() > 0) {
Element element = (Element) nodeList.item(0);
String a = "<vector xmlns:android=\"http://schemas.android.com/apk/res/android\"\n android:width=\""

+ width + "dp" + "\"\n android:height=\"" + height + "dp"

+ "\"\n android:viewportWidth=\"" + width + "\"\n android:viewportHeight=\"" + height

+ "\"\n android:tint=\"" + color

+ "\">\n <path\n android:fillColor=\"@android:color/white\"\n android:pathData=\""

+ element.getAttribute("d") + "\"/>\n</vector>\n";

byte[] vectorText = a.getBytes(StandardCharsets.UTF_8);

Files.write(Paths.get(new File(projectResourceDirectory + name + ".xml").toURI()), vectorText, StandardOpenOption.CREATE, StandardOpenOption.TRUNCATE_EXISTING);

}
} catch (Exception e) {
Toast.makeText(requireContext(), e.toString(), 3000).show();
}
}

private boolean validate(EditText name, EditText height, EditText width, EditText color, EditText path) {
if (name.getText().toString().trim().isEmpty() && name.getText().toString().trim().endsWith(".xml") && name.getText().toString().endsWith(".svg")) {
return false;
} else if (height.getText().toString().trim().isEmpty()) {
return false;
} else if (width.getText().toString().trim().isEmpty()) {
return false;
} else if (color.getText().toString().trim().isEmpty()) {
return false;
} else if (path.getText().toString().trim().isEmpty()) {
return false;
}
return !name.getText().toString().contains(".xml") && !name.getText().toString().contains(".svg");
}

private Drawable loadSvg(String path) {
Drawable drawable = null;
try {
FileInputStream fileInputStream = new FileInputStream(new File(path));
SVG svg = SVG.getFromInputStream(fileInputStream);
drawable = new PictureDrawable(svg.renderToPicture());
} catch (Exception e) {
Toast.makeText(requireContext(), e.toString(), 3000).show();
}
return drawable;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,146 @@
package com.tyron.code.ui.iconmanager;

import android.app.ProgressDialog;
import android.os.Bundle;

import android.view.ViewGroup;
import android.view.LayoutInflater;
import android.view.View;
import android.widget.TextView;
import android.widget.Toast;

import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.fragment.app.Fragment;
import androidx.appcompat.widget.Toolbar;
import androidx.recyclerview.widget.GridLayoutManager;
import androidx.recyclerview.widget.RecyclerView;

import com.google.android.material.dialog.MaterialAlertDialogBuilder;
import com.google.android.material.transition.MaterialSharedAxis;

import com.tyron.code.R;
import com.tyron.code.util.UiUtilsKt;
import com.tyron.code.ui.project.ProjectManager;
import com.tyron.completion.progress.ProgressManager;
import com.tyron.common.util.Decompress;
import com.tyron.code.ui.iconmanager.adapter.IconAdapter;

import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStream;

import java.util.ArrayList;
import org.w3c.dom.Document;

import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;

import org.w3c.dom.Node;
import org.w3c.dom.NodeList;
import org.w3c.dom.Element;

public class IconManagerFragment extends Fragment {

public static String TAG = IconManagerFragment.class.getSimpleName();
private String iconFolderDirectory, projectResourceDirectory;
private ArrayList<String> iconList = new ArrayList<>();
private ProgressDialog pDialog;

@Override
public void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);

setEnterTransition(new MaterialSharedAxis(MaterialSharedAxis.X, true));
setExitTransition(new MaterialSharedAxis(MaterialSharedAxis.X, false));

iconFolderDirectory = getPackageDirectory() + "/Icons/";
}

@Nullable

@Override

public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {

View view = inflater.inflate(R.layout.icon_manager_fragment, container, false);

pDialog = new ProgressDialog(requireContext());
RecyclerView recyclerView = view.findViewById(R.id.recyclerview);
Toolbar toolbar = view.findViewById(R.id.toolbar);
UiUtilsKt.addSystemWindowInsetToPadding(toolbar, false, true, false, false);
if (!new File(getPackageDirectory() + "/Icons/").exists()) {
showConfirmationDialog(recyclerView, pDialog);
} else {
loadIcons(iconFolderDirectory, iconList, recyclerView);
}

return view;
}

@Override

public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceState) {

}

private void showConfirmationDialog(RecyclerView recyclerView, final ProgressDialog progressDialog) {
MaterialAlertDialogBuilder builder = new MaterialAlertDialogBuilder(requireContext());
builder.setTitle("Warning!");
builder.setMessage("Do you want to extract all icons from CodeAssist?");
builder.setPositiveButton("EXTRACT", (d, w) -> {
progressDialog.setMessage("Extracting icons");
progressDialog.setCancelable(false);
progressDialog.show();
ProgressManager.getInstance().runNonCancelableAsync(() ->startExtractingIcons(progressDialog, recyclerView));
});
builder.setNegativeButton("CANCEL", null);
builder.create().show();
}

private void startExtractingIcons(final ProgressDialog progressDialog, RecyclerView recyclerView) {
Decompress.unzipFromAssets(requireContext(), "Icons.zip", getPackageDirectory());

ProgressManager.getInstance().runLater(() -> {
if (progressDialog.isShowing()) {
progressDialog.dismiss();
Toast.makeText(requireContext(), "Please restart Icon manager", 3000).show();
}
});
}

private void loadIcons(String path, ArrayList<String> list, RecyclerView recyclerView) {
list.clear();
getFileList(path, list);
recyclerView.setNestedScrollingEnabled(false);
recyclerView.setAdapter(new IconAdapter(list, requireContext()));
recyclerView.setLayoutManager(new GridLayoutManager(requireContext(), 4));
}

private String getPackageDirectory() {
return requireContext().getExternalFilesDir(null).getAbsolutePath();
}

public static void makeDirs(String path) {
if (!new File(path).exists()) {
new File(path).mkdirs();
}
}

public static void getFileList(String source, ArrayList<String> list) {
File dir = new File(source);
if (!dir.exists() || dir.isFile())
return;
File[] listFiles = dir.listFiles();
if (listFiles == null || listFiles.length <= 0)
return;
if (list == null)
return;
list.clear();
for (File file : listFiles) {
list.add(file.getAbsolutePath());
}
}
}
Loading