1 /* 2 * Copyright 2024 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 package com.android.settings.inputmethod; 18 19 import android.content.Context; 20 import android.view.InputDevice; 21 import android.view.KeyEvent; 22 import android.view.LayoutInflater; 23 import android.view.View; 24 import android.view.ViewGroup; 25 import android.widget.ImageView; 26 import android.widget.TextView; 27 28 import androidx.annotation.NonNull; 29 import androidx.annotation.Nullable; 30 import androidx.recyclerview.widget.RecyclerView; 31 32 import com.android.settings.R; 33 34 import com.google.common.collect.ImmutableList; 35 36 import java.util.ArrayList; 37 import java.util.List; 38 import java.util.Locale; 39 40 public class MouseKeysImageListAdapter extends 41 RecyclerView.Adapter<MouseKeysImageListAdapter.MouseKeyImageViewHolder> { 42 private static final String LABEL_DELIMITER = ", "; 43 private static final ImmutableList<Integer> DRAWABLE_LIST = ImmutableList.of( 44 R.drawable.mouse_keys_directional, R.drawable.mouse_keys_click, 45 R.drawable.mouse_keys_press_hold, R.drawable.mouse_keys_release, 46 R.drawable.mouse_keys_toggle_scroll, R.drawable.mouse_keys_release2); 47 private static final ImmutableList<Integer> DIRECTIONAL_CHAR_KEYCODE_LIST = ImmutableList.of( 48 KeyEvent.KEYCODE_7, KeyEvent.KEYCODE_8, KeyEvent.KEYCODE_9, KeyEvent.KEYCODE_U, 49 KeyEvent.KEYCODE_O, KeyEvent.KEYCODE_J, KeyEvent.KEYCODE_K, KeyEvent.KEYCODE_L 50 ); 51 private static final int LEFT_CLICK_CHAR_KEYCODE = 52 KeyEvent.KEYCODE_I; 53 private static final int PRESS_HOLD_CHAR_KEYCODE = 54 KeyEvent.KEYCODE_M; 55 private static final int RELEASE_CHAR_KEYCODE = 56 KeyEvent.KEYCODE_COMMA; 57 private static final ImmutableList<Integer> TOGGLE_SCROLL_CHAR_KEYCODE_LIST = ImmutableList.of( 58 KeyEvent.KEYCODE_PERIOD, KeyEvent.KEYCODE_8, KeyEvent.KEYCODE_K, KeyEvent.KEYCODE_O, 59 KeyEvent.KEYCODE_U 60 ); 61 private static final int RIGHT_CLICK_CHAR_KEYCODE = 62 KeyEvent.KEYCODE_SLASH; 63 private final List<String> mComposedSummaryList = new ArrayList<>(); 64 MouseKeysImageListAdapter(@onNull Context context, @Nullable InputDevice currentInputDevice)65 public MouseKeysImageListAdapter(@NonNull Context context, 66 @Nullable InputDevice currentInputDevice) { 67 composeSummaryForImages(context, currentInputDevice); 68 } 69 70 @NonNull 71 @Override onCreateViewHolder(@onNull ViewGroup parent, int viewType)72 public MouseKeyImageViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) { 73 View view = LayoutInflater.from(parent.getContext()) 74 .inflate(R.layout.mouse_keys_image_item, parent, false); 75 return new MouseKeyImageViewHolder(view, parent.getContext()); 76 } 77 78 @Override onBindViewHolder(@onNull MouseKeyImageViewHolder holder, int position)79 public void onBindViewHolder(@NonNull MouseKeyImageViewHolder holder, int position) { 80 if (mComposedSummaryList.isEmpty()) { 81 return; 82 } 83 ((MouseKeyImageViewHolder) holder).bindView(DRAWABLE_LIST.get(position), 84 mComposedSummaryList.get(position)); 85 } 86 87 @Override getItemCount()88 public int getItemCount() { 89 return DRAWABLE_LIST.size(); 90 } 91 composeSummaryForImages(Context context, @Nullable InputDevice currentInputDevice)92 private void composeSummaryForImages(Context context, 93 @Nullable InputDevice currentInputDevice) { 94 if (currentInputDevice == null) { 95 return; 96 } 97 mComposedSummaryList.clear(); 98 List<String> directionalLabelList = DIRECTIONAL_CHAR_KEYCODE_LIST.stream().map( 99 (key) -> getDisplayLabel(currentInputDevice, key)).toList(); 100 mComposedSummaryList.add(context.getString(R.string.mouse_keys_directional_summary, 101 String.join(LABEL_DELIMITER, directionalLabelList))); 102 String leftClickLabel = getDisplayLabel(currentInputDevice, LEFT_CLICK_CHAR_KEYCODE); 103 mComposedSummaryList.add( 104 context.getString(R.string.mouse_keys_click_summary, leftClickLabel)); 105 String pressHoldLabel = getDisplayLabel(currentInputDevice, PRESS_HOLD_CHAR_KEYCODE); 106 mComposedSummaryList.add( 107 context.getString(R.string.mouse_keys_press_hold_summary, pressHoldLabel)); 108 String releaseLabel = getDisplayLabel(currentInputDevice, RELEASE_CHAR_KEYCODE); 109 mComposedSummaryList.add( 110 context.getString(R.string.mouse_keys_release_summary, releaseLabel)); 111 List<String> toggleScrollLabelList = TOGGLE_SCROLL_CHAR_KEYCODE_LIST.stream().map( 112 (key) -> getDisplayLabel(currentInputDevice, key)).toList(); 113 mComposedSummaryList.add(context.getString(R.string.mouse_keys_toggle_scroll_summary, 114 toggleScrollLabelList.getFirst(), 115 String.join(LABEL_DELIMITER, 116 toggleScrollLabelList.subList(1, toggleScrollLabelList.size())) 117 )); 118 String rightClickLabel = getDisplayLabel(currentInputDevice, RIGHT_CLICK_CHAR_KEYCODE); 119 mComposedSummaryList.add( 120 context.getString(R.string.mouse_keys_release2_summary, rightClickLabel)); 121 } 122 getDisplayLabel(InputDevice currentInputDevice, int keycode)123 private String getDisplayLabel(InputDevice currentInputDevice, int keycode) { 124 return String.valueOf(currentInputDevice.getKeyCharacterMap().getDisplayLabel( 125 currentInputDevice.getKeyCodeForKeyLocation(keycode))).toLowerCase( 126 Locale.getDefault()); 127 } 128 129 public static class MouseKeyImageViewHolder extends RecyclerView.ViewHolder { 130 private final TextView mTextView; 131 private final ImageView mImageView; 132 private final Context mContext; 133 MouseKeyImageViewHolder(View itemView, Context context)134 public MouseKeyImageViewHolder(View itemView, Context context) { 135 super(itemView); 136 mTextView = itemView.findViewById(R.id.layout_description); 137 mImageView = itemView.findViewById(R.id.image); 138 mContext = context; 139 } 140 bindView(int drawableRes, String summary)141 void bindView(int drawableRes, String summary) { 142 mTextView.setText(summary); 143 mImageView.setImageDrawable(mContext.getDrawable(drawableRes)); 144 } 145 } 146 } 147