Allow specifying any font size. https://redmine.stoutner.com/issues/504
[PrivacyBrowser.git] / app / src / main / java / com / stoutner / privacybrowser / dialogs / FontSizeDialog.java
1 /*
2  * Copyright © 2019 Soren Stoutner <soren@stoutner.com>.
3  *
4  * This file is part of Privacy Browser <https://www.stoutner.com/privacy-browser>.
5  *
6  * Privacy Browser is free software: you can redistribute it and/or modify
7  * it under the terms of the GNU General Public License as published by
8  * the Free Software Foundation, either version 3 of the License, or
9  * (at your option) any later version.
10  *
11  * Privacy Browser is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14  * GNU General Public License for more details.
15  *
16  * You should have received a copy of the GNU General Public License
17  * along with Privacy Browser.  If not, see <http://www.gnu.org/licenses/>.
18  */
19
20 package com.stoutner.privacybrowser.dialogs;
21
22 import android.annotation.SuppressLint;
23 import android.app.Activity;
24 import android.app.AlertDialog;
25 import android.app.Dialog;
26 import android.content.Context;
27 import android.content.DialogInterface;
28 import android.content.SharedPreferences;
29 import android.os.Bundle;
30 import android.view.KeyEvent;
31 import android.view.View;
32 import android.view.Window;
33 import android.view.WindowManager;
34 import android.widget.EditText;
35
36 import androidx.annotation.NonNull;
37 import androidx.fragment.app.DialogFragment;
38 import androidx.preference.PreferenceManager;
39
40 import com.stoutner.privacybrowser.R;
41
42 public class FontSizeDialog extends DialogFragment {
43     // Define the update font size listener.
44     private UpdateFontSizeListener updateFontSizeListener;
45
46     // The public interface is used to send information back to the parent activity.
47     public interface UpdateFontSizeListener {
48         void onApplyNewFontSize(DialogFragment dialogFragment);
49     }
50
51     @Override
52     public void onAttach(@NonNull Context context) {
53         // Run the default commands.
54         super.onAttach(context);
55
56         // Get a handle for the update font size listener from the launching context.
57         updateFontSizeListener = (UpdateFontSizeListener) context;
58     }
59
60     public static FontSizeDialog displayDialog(int fontSize) {
61         // Create an arguments bundle.
62         Bundle argumentsBundle = new Bundle();
63
64         // Store the font size in the bundle.
65         argumentsBundle.putInt("font_size", fontSize);
66
67         // Create a new instance of the dialog.
68         FontSizeDialog fontSizeDialog = new FontSizeDialog();
69
70         // Add the bundle to the dialog.
71         fontSizeDialog.setArguments(argumentsBundle);
72
73         // Return the new dialog.
74         return fontSizeDialog;
75     }
76
77     // `@SuppressLing("InflateParams")` removes the warning about using null as the parent view group when inflating the alert dialog.
78     @SuppressLint("InflateParams")
79     @Override
80     @NonNull
81     public Dialog onCreateDialog(Bundle savedInstanceState) {
82         // Get a handle for the activity and the context.
83         Activity activity = getActivity();
84         Context context = getContext();
85
86         // Remove the incorrect lint warnings below that the activity and context might be null.
87         assert activity != null;
88         assert context != null;
89
90         // Use a builder to create the alert dialog.
91         AlertDialog.Builder dialogBuilder;
92
93         // Get the arguments.
94         Bundle arguments = getArguments();
95
96         // Remove the incorrect lint warning below that `getInt()` might be null.
97         assert arguments != null;
98
99         // Get the current font size.
100         int currentFontSize = arguments.getInt("font_size");
101
102         // Get a handle for the shared preferences.
103         SharedPreferences sharedPreferences = PreferenceManager.getDefaultSharedPreferences(context);
104
105         // Get the screenshot and theme preferences.
106         boolean darkTheme = sharedPreferences.getBoolean("dark_theme", false);
107         boolean allowScreenshots = sharedPreferences.getBoolean("allow_screenshots", false);
108
109         // Set the style and icon according to the theme.
110         if (darkTheme) {
111             dialogBuilder = new AlertDialog.Builder(activity, R.style.PrivacyBrowserAlertDialogDark);
112             dialogBuilder.setIcon(R.drawable.font_size_dark);
113         } else {
114             dialogBuilder = new AlertDialog.Builder(activity, R.style.PrivacyBrowserAlertDialogLight);
115             dialogBuilder.setIcon(R.drawable.font_size_light);
116         }
117
118         // Set the title.
119         dialogBuilder.setTitle(R.string.font_size);
120
121         // Set the view.  The parent view is null because it will be assigned by the alert dialog.
122         dialogBuilder.setView(activity.getLayoutInflater().inflate(R.layout.font_size_dialog, null));
123
124         // Set the close button listener.  Using `null` as the listener closes the dialog without doing anything else.
125         dialogBuilder.setNegativeButton(R.string.close, null);
126
127         // Set the apply button listener.
128         dialogBuilder.setPositiveButton(R.string.apply, (DialogInterface dialog, int which) -> {
129             // Return the dialog fragment to the parent activity.
130             updateFontSizeListener.onApplyNewFontSize(this);
131         });
132
133         // Create an alert dialog from the builder.
134         AlertDialog alertDialog = dialogBuilder.create();
135
136         // Get the alert dialog window.
137         Window dialogWindow = alertDialog.getWindow();
138
139         // Remove the incorrect lint warning below that the dialog window might be null.
140         assert dialogWindow != null;
141
142         // Disable screenshots if not allowed.
143         if (!allowScreenshots) {
144             dialogWindow.addFlags(WindowManager.LayoutParams.FLAG_SECURE);
145         }
146
147         // Display the keyboard.
148         dialogWindow.setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_STATE_VISIBLE);
149
150         // The alert dialog must be shown before items in the layout can be modified.
151         alertDialog.show();
152
153         // Get a handle for the font size edit text.
154         EditText fontSizeEditText = alertDialog.findViewById(R.id.font_size_edittext);
155
156         // Display the current font size.
157         fontSizeEditText.setText(String.valueOf(currentFontSize));
158
159         // Request focus on the font size edit text.
160         fontSizeEditText.requestFocus();
161
162         // Set the enter key on the keyboard to update the font size.
163         fontSizeEditText.setOnKeyListener((View view, int keyCode, KeyEvent keyEvent) -> {
164             // If the key event is a key-down on the `enter` key apply the new font size.
165             if ((keyEvent.getAction() == KeyEvent.ACTION_DOWN) && (keyCode == KeyEvent.KEYCODE_ENTER)) {  // The enter key was pressed.
166                 // Trigger the update font size listener and return the dialog fragment to the parent activity.
167                 updateFontSizeListener.onApplyNewFontSize((this));
168
169                 // Manually dismiss the alert dialog.
170                 alertDialog.dismiss();
171
172                 //Consume the event.
173                 return true;
174             } else {  // If any other key was pressed do not consume the event.
175                 return false;
176             }
177         });
178
179         // Return the alert dialog.
180         return alertDialog;
181     }
182 }