mirror of
https://github.com/TimeCrafters/TimeCraftersConfigurationTool.git
synced 2025-12-15 05:02:33 +00:00
Added a view to main activity layout to host Snackbars, Configurations menu is mostly functional, misc.
This commit is contained in:
@@ -28,6 +28,7 @@ dependencies {
|
||||
implementation 'androidx.appcompat:appcompat:1.1.0'
|
||||
implementation 'com.google.android.material:material:1.0.0'
|
||||
implementation 'androidx.constraintlayout:constraintlayout:1.1.3'
|
||||
implementation 'androidx.coordinatorlayout:coordinatorlayout:1.1.0'
|
||||
implementation 'androidx.vectordrawable:vectordrawable:1.1.0'
|
||||
implementation 'androidx.navigation:navigation-fragment:2.1.0'
|
||||
implementation 'androidx.navigation:navigation-ui:2.1.0'
|
||||
|
||||
@@ -33,11 +33,17 @@ import java.io.FileReader;
|
||||
import java.io.FileWriter;
|
||||
import java.io.FilenameFilter;
|
||||
import java.io.IOException;
|
||||
import java.net.URI;
|
||||
import java.nio.file.Files;
|
||||
import java.nio.file.Paths;
|
||||
import java.nio.file.StandardCopyOption;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Date;
|
||||
import java.util.HashMap;
|
||||
|
||||
public class Backend {
|
||||
private static final String TAG = "Backend";
|
||||
static private HashMap<String, Object> storage = new HashMap<>();
|
||||
static private Backend instance;
|
||||
private TACNET tacnet;
|
||||
private Server server;
|
||||
@@ -46,6 +52,10 @@ public class Backend {
|
||||
private Settings settings;
|
||||
private boolean configChanged, settingsChanged;
|
||||
|
||||
public static HashMap<String, Object> getStorage() {
|
||||
return storage;
|
||||
}
|
||||
|
||||
public Backend() {
|
||||
if (Backend.instance() != null) {
|
||||
throw(new RuntimeException("Backend instance already exists!"));
|
||||
@@ -114,10 +124,14 @@ public class Backend {
|
||||
saveConfig();
|
||||
}
|
||||
|
||||
public boolean isConfigChanged() { return configChanged; }
|
||||
public boolean hasConfigChanged() { return configChanged; }
|
||||
|
||||
public String configPath(String name) {
|
||||
return TAC.CONFIGS_PATH + File.separator + name + ".json";
|
||||
}
|
||||
|
||||
public void loadConfig(String name) {
|
||||
String path = "" + TAC.CONFIGS_PATH + File.separator + name + ".json";
|
||||
String path = configPath(name);
|
||||
File file = new File(path);
|
||||
|
||||
if (file.exists() && file.isFile()) {
|
||||
@@ -129,12 +143,38 @@ public class Backend {
|
||||
public boolean saveConfig() {
|
||||
if (config == null) { return false; }
|
||||
|
||||
final String path = "" + TAC.CONFIGS_PATH + File.separator + getConfig().getName() + ".json";
|
||||
final String path = configPath(getConfig().getName());
|
||||
configChanged = false;
|
||||
|
||||
return writeToFile(path, gsonForConfig().toJson(config));
|
||||
}
|
||||
|
||||
public boolean moveConfig(String oldName, String newName) {
|
||||
final String oldPath = configPath(oldName);
|
||||
final String newPath = configPath(newName);
|
||||
|
||||
final File oldFile = new File(oldPath);
|
||||
final File newFile = new File(newPath);
|
||||
|
||||
if (!oldFile.exists() || !oldFile.isFile()) {
|
||||
Log.e(TAG, "moveConfig: Can not move config file \"" + oldPath + "\" does not exists!");
|
||||
return false;
|
||||
}
|
||||
|
||||
if (newFile.exists() && newFile.isFile()) {
|
||||
Log.e(TAG, "moveConfig: Config file \"" + newPath + "\" already exists!");
|
||||
return false;
|
||||
}
|
||||
|
||||
return oldFile.renameTo(newFile);
|
||||
}
|
||||
|
||||
public boolean deleteConfig(String name) {
|
||||
File file = new File(configPath(name));
|
||||
|
||||
return file.delete();
|
||||
}
|
||||
|
||||
public void uploadConfig() {
|
||||
if (config != null && tacnet.isConnected()) {
|
||||
String json = "";
|
||||
@@ -149,7 +189,7 @@ public class Backend {
|
||||
}
|
||||
|
||||
public void writeNewConfig(String name) {
|
||||
String path = TAC.CONFIGS_PATH + File.separator + name + ".json";
|
||||
String path = configPath(name);
|
||||
File file = new File(path);
|
||||
|
||||
Config config = new Config(name);
|
||||
|
||||
@@ -18,6 +18,7 @@ import java.util.regex.Pattern;
|
||||
|
||||
public class ConfigurationDialog extends TimeCraftersDialog {
|
||||
private static final String TAG = "ConfigurationDialog";
|
||||
private String configName;
|
||||
|
||||
@Override
|
||||
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
|
||||
@@ -31,7 +32,14 @@ public class ConfigurationDialog extends TimeCraftersDialog {
|
||||
final Button cancel = view.findViewById(R.id.cancel);
|
||||
final Button mutate = view.findViewById(R.id.mutate);
|
||||
|
||||
title.setText("Create Configuration");
|
||||
if (getArguments() != null) {
|
||||
configName = getArguments().getString("config_name");
|
||||
title.setText("Editing " + configName);
|
||||
name.setText(configName);
|
||||
mutate.setText(getResources().getString(R.string.dialog_update));
|
||||
} else {
|
||||
title.setText("Create Configuration");
|
||||
}
|
||||
cancel.setOnClickListener(new View.OnClickListener() {
|
||||
@Override
|
||||
public void onClick(View v) {
|
||||
@@ -39,16 +47,20 @@ public class ConfigurationDialog extends TimeCraftersDialog {
|
||||
}
|
||||
});
|
||||
|
||||
// mutate.setText(getResources().getString(R.string.dialog_update));
|
||||
mutate.setOnClickListener(new View.OnClickListener() {
|
||||
@Override
|
||||
public void onClick(View v) {
|
||||
String configName = name.getText().toString();
|
||||
final String newConfigName = name.getText().toString();
|
||||
|
||||
if (isValid(configName)) {
|
||||
Backend.instance().writeNewConfig(configName);
|
||||
if (isValid(newConfigName)) {
|
||||
if (configName != null) {
|
||||
Backend.instance().moveConfig(configName, newConfigName);
|
||||
} else {
|
||||
Backend.instance().writeNewConfig(newConfigName);
|
||||
}
|
||||
dismiss();
|
||||
} else {
|
||||
// TODO: Show friendly error message
|
||||
Log.d(TAG, "onClick: InValid");
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,6 +1,11 @@
|
||||
package org.timecrafters.TimeCraftersConfigurationTool.dialogs;
|
||||
|
||||
import android.graphics.Color;
|
||||
import android.graphics.Typeface;
|
||||
import android.graphics.drawable.ColorDrawable;
|
||||
import android.os.Build;
|
||||
import android.os.Bundle;
|
||||
import android.util.Log;
|
||||
import android.view.LayoutInflater;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
@@ -10,25 +15,30 @@ import android.widget.TextView;
|
||||
|
||||
import androidx.constraintlayout.widget.ConstraintLayout;
|
||||
|
||||
import com.google.android.material.resources.TextAppearance;
|
||||
|
||||
import org.timecrafters.TimeCraftersConfigurationTool.R;
|
||||
import org.timecrafters.TimeCraftersConfigurationTool.backend.Backend;
|
||||
import org.timecrafters.TimeCraftersConfigurationTool.library.TimeCraftersDialog;
|
||||
|
||||
public class ConfirmationDialog extends TimeCraftersDialog {
|
||||
private String title, message;
|
||||
private Runnable action;
|
||||
|
||||
public ConfirmationDialog() {}
|
||||
|
||||
public ConfirmationDialog(String title, String message, Runnable action) {
|
||||
this.title = title;
|
||||
this.message = message;
|
||||
this.action = action;
|
||||
}
|
||||
|
||||
@Override
|
||||
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
|
||||
View root = super.onCreateView(inflater, container, savedInstanceState);
|
||||
|
||||
if (getArguments() != null) {
|
||||
this.title = getArguments().getString("title", "Are You Sure?");
|
||||
this.message = getArguments().getString("message", "");
|
||||
|
||||
final String actionKey = getArguments().getString("action", null);
|
||||
if (actionKey != null && Backend.getStorage().containsKey(actionKey)) {
|
||||
this.action = (Runnable) Backend.getStorage().get(actionKey);
|
||||
}
|
||||
}
|
||||
|
||||
final TextView title = root.findViewById(R.id.dialogTitle);
|
||||
final ConstraintLayout titlebar = root.findViewById(R.id.titlebar);
|
||||
final LinearLayout view = root.findViewById(R.id.dialogContent);
|
||||
@@ -37,13 +47,29 @@ public class ConfirmationDialog extends TimeCraftersDialog {
|
||||
final Button cancel = root.findViewById(R.id.cancel);
|
||||
final Button confirm = root.findViewById(R.id.confirm);
|
||||
|
||||
titlebar.setBackgroundColor(getResources().getColor(R.color.dialogAlert));
|
||||
if (getArguments() != null && getArguments().getBoolean("extreme_danger", false)) {
|
||||
titlebar.setBackgroundColor(getResources().getColor(R.color.dialogError));
|
||||
getDialog().getWindow().setDimAmount(0.8f);
|
||||
cancel.setTypeface(cancel.getTypeface(), Typeface.BOLD);
|
||||
} else {
|
||||
titlebar.setBackgroundColor(getResources().getColor(R.color.dialogAlert));
|
||||
}
|
||||
title.setText(this.title);
|
||||
messageView.setText(message);
|
||||
|
||||
cancel.setOnClickListener(new View.OnClickListener() {
|
||||
@Override
|
||||
public void onClick(View v) {
|
||||
dismiss();
|
||||
}
|
||||
});
|
||||
confirm.setOnClickListener(new View.OnClickListener() {
|
||||
@Override
|
||||
public void onClick(View v) {
|
||||
if (action != null) {
|
||||
action.run();
|
||||
}
|
||||
|
||||
dismiss();
|
||||
}
|
||||
});
|
||||
|
||||
@@ -104,7 +104,12 @@ public class GroupsFragment extends TimeCraftersFragment {
|
||||
delete.setOnClickListener(new View.OnClickListener() {
|
||||
@Override
|
||||
public void onClick(View v) {
|
||||
ConfirmationDialog dialog = new ConfirmationDialog("Are you sure?", "Really delete " + group.name + "?", null);
|
||||
ConfirmationDialog dialog = new ConfirmationDialog();
|
||||
Bundle bundle = new Bundle();
|
||||
bundle.putString("title", "Are you sure?");
|
||||
bundle.putString("message", "Delete group " + group.name + "?");
|
||||
dialog.setArguments(bundle);
|
||||
|
||||
dialog.show(getFragmentManager(), null);
|
||||
}
|
||||
});
|
||||
|
||||
@@ -1,28 +1,38 @@
|
||||
package org.timecrafters.TimeCraftersConfigurationTool.ui.settings.configurations;
|
||||
|
||||
import android.content.BroadcastReceiver;
|
||||
import android.content.Context;
|
||||
import android.os.Bundle;
|
||||
import android.view.LayoutInflater;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
import android.widget.Button;
|
||||
import android.widget.ImageButton;
|
||||
import android.widget.LinearLayout;
|
||||
import android.widget.ScrollView;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
|
||||
import com.google.android.material.floatingactionbutton.FloatingActionButton;
|
||||
import com.google.android.material.snackbar.Snackbar;
|
||||
|
||||
import org.timecrafters.TimeCraftersConfigurationTool.R;
|
||||
import org.timecrafters.TimeCraftersConfigurationTool.backend.Backend;
|
||||
import org.timecrafters.TimeCraftersConfigurationTool.dialogs.ConfigurationDialog;
|
||||
import org.timecrafters.TimeCraftersConfigurationTool.dialogs.ConfirmationDialog;
|
||||
import org.timecrafters.TimeCraftersConfigurationTool.library.TimeCraftersFragment;
|
||||
|
||||
public class ConfigurationsFragment extends TimeCraftersFragment {
|
||||
private LayoutInflater inflater;
|
||||
private LinearLayout configsContainer;
|
||||
private View root;
|
||||
|
||||
public View onCreateView(@NonNull LayoutInflater inflater,
|
||||
ViewGroup container, Bundle savedInstanceState) {
|
||||
final View root = inflater.inflate(R.layout.fragment_configuration, container, false);
|
||||
this.inflater = inflater;
|
||||
this.root = inflater.inflate(R.layout.fragment_configuration, container, false);
|
||||
final ScrollView scrollview = root.findViewById(R.id.scrollview);
|
||||
final LinearLayout configsContainer = root.findViewById(R.id.container);
|
||||
configsContainer = root.findViewById(R.id.container);
|
||||
final FloatingActionButton actionButton = root.findViewById(R.id.actionButton);
|
||||
|
||||
floatingActionButtonAutoHide(actionButton, scrollview);
|
||||
@@ -34,8 +44,16 @@ public class ConfigurationsFragment extends TimeCraftersFragment {
|
||||
}
|
||||
});
|
||||
|
||||
populateConfigFiles();
|
||||
|
||||
return root;
|
||||
}
|
||||
|
||||
private void populateConfigFiles() {
|
||||
configsContainer.removeAllViews();
|
||||
|
||||
int i = 0;
|
||||
for (String configFile : Backend.instance().configsList()) {
|
||||
for (final String configFile : Backend.instance().configsList()) {
|
||||
final String config = configFile.replace(".json", "");
|
||||
View view = inflater.inflate(R.layout.fragment_part_configuration, null);
|
||||
|
||||
@@ -45,21 +63,62 @@ public class ConfigurationsFragment extends TimeCraftersFragment {
|
||||
view.setBackgroundColor(getResources().getColor(R.color.list_odd));
|
||||
}
|
||||
|
||||
Button configName = view.findViewById(R.id.name);
|
||||
final Button configName = view.findViewById(R.id.name);
|
||||
final ImageButton rename = view.findViewById(R.id.rename);
|
||||
final ImageButton delete = view.findViewById(R.id.delete);
|
||||
configName.setText(config);
|
||||
configName.setOnClickListener(new View.OnClickListener() {
|
||||
@Override
|
||||
public void onClick(View v) {
|
||||
if (Backend.instance().getSettings().config.equals(config)) {
|
||||
return;
|
||||
}
|
||||
|
||||
Backend.instance().getSettings().config = config;
|
||||
Backend.instance().loadConfig(config);
|
||||
Backend.instance().saveSettings();
|
||||
|
||||
View snackbarHost = getActivity().findViewById(R.id.snackbar_host);
|
||||
Snackbar.make(snackbarHost, "Loaded config: " + config, Snackbar.LENGTH_LONG).show();
|
||||
}
|
||||
});
|
||||
|
||||
rename.setOnClickListener(new View.OnClickListener() {
|
||||
@Override
|
||||
public void onClick(View v) {
|
||||
ConfigurationDialog dialog = new ConfigurationDialog();
|
||||
Bundle bundle = new Bundle();
|
||||
bundle.putString("config_name", config);
|
||||
dialog.setArguments(bundle);
|
||||
dialog.show(getFragmentManager(), null);
|
||||
}
|
||||
});
|
||||
|
||||
delete.setOnClickListener(new View.OnClickListener() {
|
||||
@Override
|
||||
public void onClick(View v) {
|
||||
ConfirmationDialog dialog = new ConfirmationDialog();
|
||||
Bundle bundle = new Bundle();
|
||||
final String actionKey = "delete_configuration";
|
||||
bundle.putString("title", "Are you sure?");
|
||||
bundle.putString("message", "Destroy configuration " + config + "?");
|
||||
bundle.putString("action", actionKey);
|
||||
bundle.putBoolean("extreme_danger", true);
|
||||
Runnable action = new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
Backend.instance().deleteConfig(config);
|
||||
}
|
||||
} ;
|
||||
Backend.getStorage().put(actionKey, action);
|
||||
dialog.setArguments(bundle);
|
||||
|
||||
dialog.show(getFragmentManager(), null);
|
||||
}
|
||||
});
|
||||
|
||||
i++;
|
||||
configsContainer.addView(view);
|
||||
}
|
||||
|
||||
return root;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -20,6 +20,13 @@
|
||||
app:layout_constraintVertical_bias="0.0"
|
||||
app:navGraph="@navigation/mobile_navigation" />
|
||||
|
||||
<androidx.coordinatorlayout.widget.CoordinatorLayout
|
||||
android:id="@+id/snackbar_host"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
app:layout_constraintBottom_toBottomOf="@id/nav_host_fragment"
|
||||
app:layout_constraintStart_toStartOf="@id/nav_host_fragment" />
|
||||
|
||||
<com.google.android.material.bottomnavigation.BottomNavigationView
|
||||
android:id="@+id/nav_view"
|
||||
android:layout_width="0dp"
|
||||
|
||||
Reference in New Issue
Block a user