13bf66744d61d18c66d46f2608de0467ad3df0268Mopria/*
23bf66744d61d18c66d46f2608de0467ad3df0268Mopria * Copyright (C) 2016 The Android Open Source Project
33bf66744d61d18c66d46f2608de0467ad3df0268Mopria * Copyright (C) 2016 Mopria Alliance, Inc.
43bf66744d61d18c66d46f2608de0467ad3df0268Mopria *
53bf66744d61d18c66d46f2608de0467ad3df0268Mopria * Licensed under the Apache License, Version 2.0 (the "License");
63bf66744d61d18c66d46f2608de0467ad3df0268Mopria * you may not use this file except in compliance with the License.
73bf66744d61d18c66d46f2608de0467ad3df0268Mopria * You may obtain a copy of the License at
83bf66744d61d18c66d46f2608de0467ad3df0268Mopria *
93bf66744d61d18c66d46f2608de0467ad3df0268Mopria *      http://www.apache.org/licenses/LICENSE-2.0
103bf66744d61d18c66d46f2608de0467ad3df0268Mopria *
113bf66744d61d18c66d46f2608de0467ad3df0268Mopria * Unless required by applicable law or agreed to in writing, software
123bf66744d61d18c66d46f2608de0467ad3df0268Mopria * distributed under the License is distributed on an "AS IS" BASIS,
133bf66744d61d18c66d46f2608de0467ad3df0268Mopria * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
143bf66744d61d18c66d46f2608de0467ad3df0268Mopria * See the License for the specific language governing permissions and
153bf66744d61d18c66d46f2608de0467ad3df0268Mopria * limitations under the License.
163bf66744d61d18c66d46f2608de0467ad3df0268Mopria */
173bf66744d61d18c66d46f2608de0467ad3df0268Mopria
183bf66744d61d18c66d46f2608de0467ad3df0268Mopriapackage com.android.bips.ui;
193bf66744d61d18c66d46f2608de0467ad3df0268Mopria
203bf66744d61d18c66d46f2608de0467ad3df0268Mopriaimport android.annotation.SuppressLint;
213bf66744d61d18c66d46f2608de0467ad3df0268Mopriaimport android.app.AlertDialog;
223bf66744d61d18c66d46f2608de0467ad3df0268Mopriaimport android.content.Context;
233bf66744d61d18c66d46f2608de0467ad3df0268Mopriaimport android.os.Bundle;
243bf66744d61d18c66d46f2608de0467ad3df0268Mopriaimport android.text.Editable;
253bf66744d61d18c66d46f2608de0467ad3df0268Mopriaimport android.text.TextWatcher;
263bf66744d61d18c66d46f2608de0467ad3df0268Mopriaimport android.util.Log;
273bf66744d61d18c66d46f2608de0467ad3df0268Mopriaimport android.view.KeyEvent;
283bf66744d61d18c66d46f2608de0467ad3df0268Mopriaimport android.view.View;
293bf66744d61d18c66d46f2608de0467ad3df0268Mopriaimport android.view.Window;
303bf66744d61d18c66d46f2608de0467ad3df0268Mopriaimport android.view.WindowManager;
313bf66744d61d18c66d46f2608de0467ad3df0268Mopriaimport android.view.inputmethod.EditorInfo;
323bf66744d61d18c66d46f2608de0467ad3df0268Mopriaimport android.view.inputmethod.InputMethodManager;
333bf66744d61d18c66d46f2608de0467ad3df0268Mopriaimport android.widget.Button;
343bf66744d61d18c66d46f2608de0467ad3df0268Mopriaimport android.widget.ProgressBar;
353bf66744d61d18c66d46f2608de0467ad3df0268Mopriaimport android.widget.TextView;
363bf66744d61d18c66d46f2608de0467ad3df0268Mopria
373bf66744d61d18c66d46f2608de0467ad3df0268Mopriaimport com.android.bips.R;
383bf66744d61d18c66d46f2608de0467ad3df0268Mopriaimport com.android.bips.discovery.DiscoveredPrinter;
393bf66744d61d18c66d46f2608de0467ad3df0268Mopriaimport com.android.bips.discovery.ManualDiscovery;
403bf66744d61d18c66d46f2608de0467ad3df0268Mopria
413bf66744d61d18c66d46f2608de0467ad3df0268Mopriaimport java.util.regex.Matcher;
423bf66744d61d18c66d46f2608de0467ad3df0268Mopriaimport java.util.regex.Pattern;
433bf66744d61d18c66d46f2608de0467ad3df0268Mopria
443bf66744d61d18c66d46f2608de0467ad3df0268Mopria/**
453bf66744d61d18c66d46f2608de0467ad3df0268Mopria * Allows the user to enter printer address manually
463bf66744d61d18c66d46f2608de0467ad3df0268Mopria */
473bf66744d61d18c66d46f2608de0467ad3df0268Mopriaclass AddManualPrinterDialog extends AlertDialog implements TextWatcher,
483bf66744d61d18c66d46f2608de0467ad3df0268Mopria        TextView.OnEditorActionListener, View.OnKeyListener {
493bf66744d61d18c66d46f2608de0467ad3df0268Mopria    private static final String TAG = AddManualPrinterDialog.class.getSimpleName();
503bf66744d61d18c66d46f2608de0467ad3df0268Mopria    private static final boolean DEBUG = false;
513bf66744d61d18c66d46f2608de0467ad3df0268Mopria
523bf66744d61d18c66d46f2608de0467ad3df0268Mopria    /**
533bf66744d61d18c66d46f2608de0467ad3df0268Mopria     * A regex that matches IP addresses and domain names like "192.168.1.101" and
543bf66744d61d18c66d46f2608de0467ad3df0268Mopria     * "printer1.company.com"
553bf66744d61d18c66d46f2608de0467ad3df0268Mopria     */
563bf66744d61d18c66d46f2608de0467ad3df0268Mopria    private static final String NAME_IP_REGEX =
573bf66744d61d18c66d46f2608de0467ad3df0268Mopria            "[a-zA-Z0-9]+(\\-[a-zA-Z0-9]+)*(\\.[a-zA-Z0-9]+(\\-[a-zA-Z0-9]+)*)*";
583bf66744d61d18c66d46f2608de0467ad3df0268Mopria    private static final String HOSTNAME_REGEXP = "^" + NAME_IP_REGEX + "$";
593bf66744d61d18c66d46f2608de0467ad3df0268Mopria    private static final Pattern HOSTNAME_PATTERN = Pattern.compile(HOSTNAME_REGEXP);
603bf66744d61d18c66d46f2608de0467ad3df0268Mopria
613bf66744d61d18c66d46f2608de0467ad3df0268Mopria    private final ManualDiscovery mDiscovery;
623bf66744d61d18c66d46f2608de0467ad3df0268Mopria    private TextView mHostnameView;
633bf66744d61d18c66d46f2608de0467ad3df0268Mopria    private Button mAddButton;
643bf66744d61d18c66d46f2608de0467ad3df0268Mopria    private ProgressBar mProgressBar;
653bf66744d61d18c66d46f2608de0467ad3df0268Mopria
663bf66744d61d18c66d46f2608de0467ad3df0268Mopria    AddManualPrinterDialog(Context context, ManualDiscovery discovery) {
673bf66744d61d18c66d46f2608de0467ad3df0268Mopria        super(context);
683bf66744d61d18c66d46f2608de0467ad3df0268Mopria        mDiscovery = discovery;
693bf66744d61d18c66d46f2608de0467ad3df0268Mopria    }
703bf66744d61d18c66d46f2608de0467ad3df0268Mopria
713bf66744d61d18c66d46f2608de0467ad3df0268Mopria    @SuppressLint("InflateParams")
723bf66744d61d18c66d46f2608de0467ad3df0268Mopria    @Override
733bf66744d61d18c66d46f2608de0467ad3df0268Mopria    protected void onCreate(Bundle savedInstanceState) {
743bf66744d61d18c66d46f2608de0467ad3df0268Mopria        if (DEBUG) Log.d(TAG, "onCreate");
753bf66744d61d18c66d46f2608de0467ad3df0268Mopria        View view = getLayoutInflater().inflate(R.layout.manual_printer_add, null);
763bf66744d61d18c66d46f2608de0467ad3df0268Mopria        setView(view);
773bf66744d61d18c66d46f2608de0467ad3df0268Mopria        setTitle(R.string.add_manual_printer);
783bf66744d61d18c66d46f2608de0467ad3df0268Mopria        setButton(AlertDialog.BUTTON_NEGATIVE, getContext().getString(android.R.string.cancel),
793bf66744d61d18c66d46f2608de0467ad3df0268Mopria                (OnClickListener) null);
803bf66744d61d18c66d46f2608de0467ad3df0268Mopria        setButton(AlertDialog.BUTTON_POSITIVE, getContext().getString(R.string.add),
813bf66744d61d18c66d46f2608de0467ad3df0268Mopria                (OnClickListener) null);
823bf66744d61d18c66d46f2608de0467ad3df0268Mopria
833bf66744d61d18c66d46f2608de0467ad3df0268Mopria        super.onCreate(savedInstanceState);
843bf66744d61d18c66d46f2608de0467ad3df0268Mopria        mAddButton = getButton(AlertDialog.BUTTON_POSITIVE);
853bf66744d61d18c66d46f2608de0467ad3df0268Mopria        mHostnameView = (TextView) findViewById(R.id.hostname);
863bf66744d61d18c66d46f2608de0467ad3df0268Mopria        mProgressBar = (ProgressBar) findViewById(R.id.progress);
873bf66744d61d18c66d46f2608de0467ad3df0268Mopria
883bf66744d61d18c66d46f2608de0467ad3df0268Mopria        mAddButton.setOnClickListener(view1 -> addPrinter());
893bf66744d61d18c66d46f2608de0467ad3df0268Mopria
903bf66744d61d18c66d46f2608de0467ad3df0268Mopria        // Update add button as contents change
913bf66744d61d18c66d46f2608de0467ad3df0268Mopria        mHostnameView.addTextChangedListener(this);
923bf66744d61d18c66d46f2608de0467ad3df0268Mopria        mHostnameView.setOnEditorActionListener(this);
933bf66744d61d18c66d46f2608de0467ad3df0268Mopria        mHostnameView.setOnKeyListener(this);
943bf66744d61d18c66d46f2608de0467ad3df0268Mopria
953bf66744d61d18c66d46f2608de0467ad3df0268Mopria        // Force open keyboard if appropriate
963bf66744d61d18c66d46f2608de0467ad3df0268Mopria        openKeyboard(mHostnameView);
973bf66744d61d18c66d46f2608de0467ad3df0268Mopria
983bf66744d61d18c66d46f2608de0467ad3df0268Mopria        updateButtonState();
993bf66744d61d18c66d46f2608de0467ad3df0268Mopria    }
1003bf66744d61d18c66d46f2608de0467ad3df0268Mopria
1013bf66744d61d18c66d46f2608de0467ad3df0268Mopria    private void openKeyboard(TextView view) {
1023bf66744d61d18c66d46f2608de0467ad3df0268Mopria        Window window = getWindow();
1033bf66744d61d18c66d46f2608de0467ad3df0268Mopria        if (window != null) {
1043bf66744d61d18c66d46f2608de0467ad3df0268Mopria            window.setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_STATE_VISIBLE);
1053bf66744d61d18c66d46f2608de0467ad3df0268Mopria        }
1063bf66744d61d18c66d46f2608de0467ad3df0268Mopria
1073bf66744d61d18c66d46f2608de0467ad3df0268Mopria        view.requestFocus();
1083bf66744d61d18c66d46f2608de0467ad3df0268Mopria        InputMethodManager imm = (InputMethodManager) getContext()
1093bf66744d61d18c66d46f2608de0467ad3df0268Mopria                .getSystemService(Context.INPUT_METHOD_SERVICE);
1103bf66744d61d18c66d46f2608de0467ad3df0268Mopria        imm.showSoftInput(view, InputMethodManager.SHOW_IMPLICIT);
1113bf66744d61d18c66d46f2608de0467ad3df0268Mopria    }
1123bf66744d61d18c66d46f2608de0467ad3df0268Mopria
1133bf66744d61d18c66d46f2608de0467ad3df0268Mopria    private void updateButtonState() {
1143bf66744d61d18c66d46f2608de0467ad3df0268Mopria        String hostname = mHostnameView.getText().toString();
1153bf66744d61d18c66d46f2608de0467ad3df0268Mopria        Matcher hostMatch = HOSTNAME_PATTERN.matcher(hostname);
1163bf66744d61d18c66d46f2608de0467ad3df0268Mopria
1173bf66744d61d18c66d46f2608de0467ad3df0268Mopria        mAddButton.setEnabled(hostMatch.matches());
1183bf66744d61d18c66d46f2608de0467ad3df0268Mopria    }
1193bf66744d61d18c66d46f2608de0467ad3df0268Mopria
1203bf66744d61d18c66d46f2608de0467ad3df0268Mopria    /** Attempt to add the printer based on current data */
1213bf66744d61d18c66d46f2608de0467ad3df0268Mopria    private void addPrinter() {
1223bf66744d61d18c66d46f2608de0467ad3df0268Mopria        // Disable other actions while we are checking
1233bf66744d61d18c66d46f2608de0467ad3df0268Mopria        mAddButton.setEnabled(false);
1243bf66744d61d18c66d46f2608de0467ad3df0268Mopria        mHostnameView.setEnabled(false);
1253bf66744d61d18c66d46f2608de0467ad3df0268Mopria        mProgressBar.setVisibility(View.VISIBLE);
1263bf66744d61d18c66d46f2608de0467ad3df0268Mopria
1273bf66744d61d18c66d46f2608de0467ad3df0268Mopria        // Begin an attempt to add the printer
1283bf66744d61d18c66d46f2608de0467ad3df0268Mopria        mDiscovery.addManualPrinter(mHostnameView.getText().toString(),
1293bf66744d61d18c66d46f2608de0467ad3df0268Mopria                new ManualDiscovery.PrinterAddCallback() {
1303bf66744d61d18c66d46f2608de0467ad3df0268Mopria                    @Override
1313bf66744d61d18c66d46f2608de0467ad3df0268Mopria                    public void onFound(DiscoveredPrinter printer, boolean supported) {
1323bf66744d61d18c66d46f2608de0467ad3df0268Mopria                        if (supported) {
1333bf66744d61d18c66d46f2608de0467ad3df0268Mopria                            // Success case
1343bf66744d61d18c66d46f2608de0467ad3df0268Mopria                            dismiss();
1353bf66744d61d18c66d46f2608de0467ad3df0268Mopria                        } else {
1363bf66744d61d18c66d46f2608de0467ad3df0268Mopria                            error(getContext().getString(R.string.printer_not_supported));
1373bf66744d61d18c66d46f2608de0467ad3df0268Mopria                        }
1383bf66744d61d18c66d46f2608de0467ad3df0268Mopria                    }
1393bf66744d61d18c66d46f2608de0467ad3df0268Mopria
1403bf66744d61d18c66d46f2608de0467ad3df0268Mopria                    @Override
1413bf66744d61d18c66d46f2608de0467ad3df0268Mopria                    public void onNotFound() {
1423bf66744d61d18c66d46f2608de0467ad3df0268Mopria                        error(getContext().getString(R.string.no_printer_found));
1433bf66744d61d18c66d46f2608de0467ad3df0268Mopria                    }
1443bf66744d61d18c66d46f2608de0467ad3df0268Mopria                });
1453bf66744d61d18c66d46f2608de0467ad3df0268Mopria    }
1463bf66744d61d18c66d46f2608de0467ad3df0268Mopria
1473bf66744d61d18c66d46f2608de0467ad3df0268Mopria    /** Inform user of error and allow them to correct it */
1483bf66744d61d18c66d46f2608de0467ad3df0268Mopria    private void error(String message) {
1493bf66744d61d18c66d46f2608de0467ad3df0268Mopria        mProgressBar.setVisibility(View.GONE);
1503bf66744d61d18c66d46f2608de0467ad3df0268Mopria        mHostnameView.setError(message);
1513bf66744d61d18c66d46f2608de0467ad3df0268Mopria        mHostnameView.setEnabled(true);
1523bf66744d61d18c66d46f2608de0467ad3df0268Mopria        openKeyboard(mHostnameView);
1533bf66744d61d18c66d46f2608de0467ad3df0268Mopria    }
1543bf66744d61d18c66d46f2608de0467ad3df0268Mopria
1553bf66744d61d18c66d46f2608de0467ad3df0268Mopria    @Override
1563bf66744d61d18c66d46f2608de0467ad3df0268Mopria    public void beforeTextChanged(CharSequence charSequence, int start, int count, int after) {
1573bf66744d61d18c66d46f2608de0467ad3df0268Mopria    }
1583bf66744d61d18c66d46f2608de0467ad3df0268Mopria
1593bf66744d61d18c66d46f2608de0467ad3df0268Mopria    @Override
1603bf66744d61d18c66d46f2608de0467ad3df0268Mopria    public void onTextChanged(CharSequence charSequence, int start, int before, int count) {
1613bf66744d61d18c66d46f2608de0467ad3df0268Mopria    }
1623bf66744d61d18c66d46f2608de0467ad3df0268Mopria
1633bf66744d61d18c66d46f2608de0467ad3df0268Mopria    @Override
1643bf66744d61d18c66d46f2608de0467ad3df0268Mopria    public void afterTextChanged(Editable editable) {
1653bf66744d61d18c66d46f2608de0467ad3df0268Mopria        updateButtonState();
1663bf66744d61d18c66d46f2608de0467ad3df0268Mopria    }
1673bf66744d61d18c66d46f2608de0467ad3df0268Mopria
1683bf66744d61d18c66d46f2608de0467ad3df0268Mopria    @Override
1693bf66744d61d18c66d46f2608de0467ad3df0268Mopria    public boolean onEditorAction(TextView textView, int id, KeyEvent keyEvent) {
1703bf66744d61d18c66d46f2608de0467ad3df0268Mopria        if (id == EditorInfo.IME_ACTION_DONE && mAddButton.isEnabled()) {
1713bf66744d61d18c66d46f2608de0467ad3df0268Mopria            addPrinter();
1723bf66744d61d18c66d46f2608de0467ad3df0268Mopria            return true;
1733bf66744d61d18c66d46f2608de0467ad3df0268Mopria        }
1743bf66744d61d18c66d46f2608de0467ad3df0268Mopria        return false;
1753bf66744d61d18c66d46f2608de0467ad3df0268Mopria    }
1763bf66744d61d18c66d46f2608de0467ad3df0268Mopria
1773bf66744d61d18c66d46f2608de0467ad3df0268Mopria    @Override
1783bf66744d61d18c66d46f2608de0467ad3df0268Mopria    public boolean onKey(View view, int keyCode, KeyEvent keyEvent) {
1793bf66744d61d18c66d46f2608de0467ad3df0268Mopria        if (keyCode == KeyEvent.KEYCODE_ENTER && mAddButton.isEnabled()) {
1803bf66744d61d18c66d46f2608de0467ad3df0268Mopria            addPrinter();
1813bf66744d61d18c66d46f2608de0467ad3df0268Mopria            return true;
1823bf66744d61d18c66d46f2608de0467ad3df0268Mopria        }
1833bf66744d61d18c66d46f2608de0467ad3df0268Mopria        return false;
1843bf66744d61d18c66d46f2608de0467ad3df0268Mopria    }
1853bf66744d61d18c66d46f2608de0467ad3df0268Mopria}