Home | History | Annotate | Download | only in ui
      1 /*
      2  * Copyright (C) 2016 The Android Open Source Project
      3  * Copyright (C) 2016 Mopria Alliance, Inc.
      4  *
      5  * Licensed under the Apache License, Version 2.0 (the "License");
      6  * you may not use this file except in compliance with the License.
      7  * You may obtain a copy of the License at
      8  *
      9  *      http://www.apache.org/licenses/LICENSE-2.0
     10  *
     11  * Unless required by applicable law or agreed to in writing, software
     12  * distributed under the License is distributed on an "AS IS" BASIS,
     13  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     14  * See the License for the specific language governing permissions and
     15  * limitations under the License.
     16  */
     17 
     18 package com.android.bips.ui;
     19 
     20 import android.annotation.SuppressLint;
     21 import android.app.Activity;
     22 import android.app.AlertDialog;
     23 import android.content.Context;
     24 import android.net.Uri;
     25 import android.os.Bundle;
     26 import android.text.Editable;
     27 import android.text.TextWatcher;
     28 import android.util.Log;
     29 import android.view.KeyEvent;
     30 import android.view.View;
     31 import android.view.Window;
     32 import android.view.WindowManager;
     33 import android.view.inputmethod.EditorInfo;
     34 import android.view.inputmethod.InputMethodManager;
     35 import android.widget.Button;
     36 import android.widget.ProgressBar;
     37 import android.widget.TextView;
     38 
     39 import com.android.bips.R;
     40 import com.android.bips.discovery.DiscoveredPrinter;
     41 import com.android.bips.discovery.ManualDiscovery;
     42 
     43 import java.util.regex.Matcher;
     44 import java.util.regex.Pattern;
     45 
     46 /**
     47  * Allows the user to enter printer address manually
     48  */
     49 class AddManualPrinterDialog extends AlertDialog implements TextWatcher,
     50         TextView.OnEditorActionListener, View.OnKeyListener, ManualDiscovery.PrinterAddCallback {
     51     private static final String TAG = AddManualPrinterDialog.class.getSimpleName();
     52     private static final boolean DEBUG = false;
     53 
     54     /**
     55      * A regex matching any printer URI with optional protocol, port and path.
     56      */
     57     private static final String URI_REGEX =
     58             "(ipp[s]?://)?[a-zA-Z0-9]+(\\-[a-zA-Z0-9]+)*(\\.[a-zA-Z0-9]+(\\-[a-zA-Z0-9]+)*)*(:[0-9]+)?(/.*)?";
     59     private static final String FULL_URI_REGEX = "^" + URI_REGEX + "$";
     60     private static final Pattern FULL_URI_PATTERN = Pattern.compile(FULL_URI_REGEX);
     61 
     62     private final ManualDiscovery mDiscovery;
     63     private final Activity mActivity;
     64     private TextView mHostnameView;
     65     private Button mAddButton;
     66     private ProgressBar mProgressBar;
     67 
     68     AddManualPrinterDialog(Activity activity, ManualDiscovery discovery) {
     69         super(activity);
     70         mDiscovery = discovery;
     71         mActivity = activity;
     72     }
     73 
     74     @SuppressLint("InflateParams")
     75     @Override
     76     protected void onCreate(Bundle savedInstanceState) {
     77         if (DEBUG) Log.d(TAG, "onCreate");
     78         View view = getLayoutInflater().inflate(R.layout.manual_printer_add, null);
     79         setView(view);
     80         setTitle(R.string.add_printer_by_ip);
     81         setButton(AlertDialog.BUTTON_NEGATIVE, getContext().getString(android.R.string.cancel),
     82                 (OnClickListener) null);
     83         setButton(AlertDialog.BUTTON_POSITIVE, getContext().getString(R.string.add),
     84                 (OnClickListener) null);
     85 
     86         super.onCreate(savedInstanceState);
     87         mAddButton = getButton(AlertDialog.BUTTON_POSITIVE);
     88         mHostnameView = findViewById(R.id.hostname);
     89         mProgressBar = findViewById(R.id.progress);
     90 
     91         mAddButton.setOnClickListener(view1 -> addPrinter());
     92 
     93         // Update add button as contents change
     94         mHostnameView.addTextChangedListener(this);
     95         mHostnameView.setOnEditorActionListener(this);
     96         mHostnameView.setOnKeyListener(this);
     97 
     98         // Force open keyboard if appropriate
     99         openKeyboard(mHostnameView);
    100 
    101         updateButtonState();
    102     }
    103 
    104     @Override
    105     protected void onStop() {
    106         if (DEBUG) Log.d(TAG, "onStop()");
    107         super.onStop();
    108         mDiscovery.cancelAddManualPrinter(this);
    109     }
    110 
    111     private void openKeyboard(TextView view) {
    112         Window window = getWindow();
    113         if (window != null) {
    114             window.setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_STATE_VISIBLE);
    115         }
    116 
    117         view.requestFocus();
    118         InputMethodManager imm = (InputMethodManager) getContext()
    119                 .getSystemService(Context.INPUT_METHOD_SERVICE);
    120         imm.showSoftInput(view, InputMethodManager.SHOW_IMPLICIT);
    121     }
    122 
    123     private void updateButtonState() {
    124         String hostname = mHostnameView.getText().toString();
    125         Matcher uriMatcher = FULL_URI_PATTERN.matcher(hostname);
    126         mAddButton.setEnabled(uriMatcher.matches());
    127     }
    128 
    129     /** Attempt to add the printer based on current data */
    130     private void addPrinter() {
    131         // Disable other actions while we are checking
    132         mAddButton.setEnabled(false);
    133         mHostnameView.setEnabled(false);
    134         mProgressBar.setVisibility(View.VISIBLE);
    135 
    136         // Begin an attempt to add the printer
    137         String uriString = mHostnameView.getText().toString();
    138         Uri printerUri;
    139         if (uriString.contains("://")) {
    140             printerUri = Uri.parse(uriString);
    141         } else {
    142             // create a schemeless URI
    143             printerUri = Uri.parse("://" + uriString);
    144         }
    145         mDiscovery.addManualPrinter(printerUri, this);
    146     }
    147 
    148     @Override
    149     public void onFound(DiscoveredPrinter printer, boolean supported) {
    150         if (supported) {
    151             // Success case
    152             dismiss();
    153             mActivity.finish();
    154         } else {
    155             error(getContext().getString(R.string.printer_not_supported));
    156         }
    157     }
    158 
    159     @Override
    160     public void onNotFound() {
    161         error(getContext().getString(R.string.no_printer_found));
    162     }
    163 
    164     /** Inform user of error and allow them to correct it */
    165     private void error(String message) {
    166         mProgressBar.setVisibility(View.GONE);
    167         mHostnameView.setError(message);
    168         mHostnameView.setEnabled(true);
    169         openKeyboard(mHostnameView);
    170     }
    171 
    172     @Override
    173     public void beforeTextChanged(CharSequence charSequence, int start, int count, int after) {
    174     }
    175 
    176     @Override
    177     public void onTextChanged(CharSequence charSequence, int start, int before, int count) {
    178     }
    179 
    180     @Override
    181     public void afterTextChanged(Editable editable) {
    182         updateButtonState();
    183     }
    184 
    185     @Override
    186     public boolean onEditorAction(TextView textView, int id, KeyEvent keyEvent) {
    187         if (id == EditorInfo.IME_ACTION_DONE && mAddButton.isEnabled()) {
    188             addPrinter();
    189             return true;
    190         }
    191         return false;
    192     }
    193 
    194     @Override
    195     public boolean onKey(View view, int keyCode, KeyEvent keyEvent) {
    196         if (keyCode == KeyEvent.KEYCODE_ENTER && mAddButton.isEnabled()) {
    197             addPrinter();
    198             return true;
    199         }
    200         return false;
    201     }
    202 }
    203