NekoX/TMessagesProj/src/main/java/org/telegram/ui/ActionBar/ActionBarMenuItem.java

605 lines
24 KiB
Java
Raw Normal View History

/*
2015-10-29 18:10:07 +01:00
* This is the source code of Telegram for Android v. 3.x.x.
* It is licensed under GNU GPL v. 2 or later.
* You should have received a copy of the license in this archive (see LICENSE).
*
* Copyright Nikolai Kudashov, 2013-2016.
*/
2014-11-13 21:10:14 +01:00
package org.telegram.ui.ActionBar;
import android.content.Context;
import android.graphics.Rect;
import android.os.Build;
import android.text.Editable;
import android.text.TextWatcher;
2015-01-02 23:15:07 +01:00
import android.util.TypedValue;
import android.view.ActionMode;
import android.view.ContextMenu;
import android.view.Gravity;
import android.view.KeyEvent;
import android.view.Menu;
import android.view.MenuItem;
import android.view.MotionEvent;
import android.view.View;
import android.view.WindowManager;
import android.view.inputmethod.EditorInfo;
import android.widget.EditText;
import android.widget.FrameLayout;
import android.widget.ImageView;
import android.widget.LinearLayout;
import android.widget.TextView;
2015-09-24 22:52:02 +02:00
import org.telegram.messenger.AndroidUtilities;
import org.telegram.messenger.LocaleController;
import org.telegram.messenger.R;
2015-09-24 22:52:02 +02:00
import org.telegram.messenger.AnimationCompat.ViewProxy;
2015-02-01 19:51:02 +01:00
import org.telegram.ui.Components.FrameLayoutFixed;
import org.telegram.ui.Components.LayoutHelper;
import java.lang.reflect.Field;
2015-02-01 19:51:02 +01:00
public class ActionBarMenuItem extends FrameLayoutFixed {
2015-01-02 23:15:07 +01:00
public static class ActionBarMenuItemSearchListener {
2015-05-21 23:27:27 +02:00
public void onSearchExpand() {
}
2015-06-29 19:12:11 +02:00
public boolean canCollapseSearch() {
2015-05-21 23:27:27 +02:00
return true;
}
2015-06-29 19:12:11 +02:00
public void onSearchCollapse() {
}
2015-05-21 23:27:27 +02:00
public void onTextChanged(EditText editText) {
}
public void onSearchPressed(EditText editText) {
}
}
public interface ActionBarMenuItemDelegate {
void onItemClick(int id);
}
private ActionBarPopupWindow.ActionBarPopupWindowLayout popupLayout;
private ActionBarMenu parentMenu;
private ActionBarPopupWindow popupWindow;
private EditText searchField;
2015-01-02 23:15:07 +01:00
private ImageView clearButton;
2015-02-01 19:51:02 +01:00
protected ImageView iconView;
2015-01-02 23:15:07 +01:00
private FrameLayout searchContainer;
private boolean isSearchField = false;
private ActionBarMenuItemSearchListener listener;
private Rect rect;
private int[] location;
private View selectedMenuView;
private Runnable showMenuRunnable;
2014-11-14 16:40:15 +01:00
private boolean showFromBottom;
2014-11-17 03:44:57 +01:00
private int menuHeight = AndroidUtilities.dp(16);
2015-02-01 19:51:02 +01:00
private int subMenuOpenSide = 0;
2015-05-21 23:27:27 +02:00
private ActionBarMenuItemDelegate delegate;
2015-06-29 19:12:11 +02:00
private boolean allowCloseAnimation = true;
2015-07-22 20:56:37 +02:00
protected boolean overrideMenuClick;
private boolean processedPopupClick;
2016-04-22 15:49:00 +02:00
public ActionBarMenuItem(Context context, ActionBarMenu menu, int backgroundColor) {
super(context);
2016-04-22 15:49:00 +02:00
if (backgroundColor != 0) {
setBackgroundDrawable(Theme.createBarSelectorDrawable(backgroundColor));
}
parentMenu = menu;
2015-02-01 19:51:02 +01:00
iconView = new ImageView(context);
iconView.setScaleType(ImageView.ScaleType.CENTER);
addView(iconView);
LayoutParams layoutParams = (LayoutParams) iconView.getLayoutParams();
layoutParams.width = LayoutHelper.MATCH_PARENT;
layoutParams.height = LayoutHelper.MATCH_PARENT;
2015-02-01 19:51:02 +01:00
iconView.setLayoutParams(layoutParams);
}
@Override
public boolean onTouchEvent(MotionEvent event) {
if (event.getActionMasked() == MotionEvent.ACTION_DOWN) {
if (hasSubMenu() && (popupWindow == null || popupWindow != null && !popupWindow.isShowing())) {
showMenuRunnable = new Runnable() {
@Override
public void run() {
if (getParent() != null) {
getParent().requestDisallowInterceptTouchEvent(true);
}
toggleSubMenu();
}
};
AndroidUtilities.runOnUIThread(showMenuRunnable, 200);
}
} else if (event.getActionMasked() == MotionEvent.ACTION_MOVE) {
if (hasSubMenu() && (popupWindow == null || popupWindow != null && !popupWindow.isShowing())) {
if (event.getY() > getHeight()) {
if (getParent() != null) {
getParent().requestDisallowInterceptTouchEvent(true);
}
toggleSubMenu();
return true;
}
} else if (popupWindow != null && popupWindow.isShowing()) {
getLocationOnScreen(location);
float x = event.getX() + location[0];
float y = event.getY() + location[1];
popupLayout.getLocationOnScreen(location);
x -= location[0];
y -= location[1];
selectedMenuView = null;
2015-07-22 20:56:37 +02:00
for (int a = 0; a < popupLayout.getItemsCount(); a++) {
View child = popupLayout.getItemAt(a);
child.getHitRect(rect);
2015-05-21 23:27:27 +02:00
if ((Integer) child.getTag() < 100) {
if (!rect.contains((int) x, (int) y)) {
child.setPressed(false);
child.setSelected(false);
2015-07-22 20:56:37 +02:00
if (Build.VERSION.SDK_INT == 21) {
child.getBackground().setVisible(false, false);
}
} else {
child.setPressed(true);
child.setSelected(true);
if (Build.VERSION.SDK_INT >= 21) {
2015-07-22 20:56:37 +02:00
if (Build.VERSION.SDK_INT == 21) {
child.getBackground().setVisible(true, false);
}
child.drawableHotspotChanged(x, y - child.getTop());
}
selectedMenuView = child;
}
}
}
}
} else if (popupWindow != null && popupWindow.isShowing() && event.getActionMasked() == MotionEvent.ACTION_UP) {
if (selectedMenuView != null) {
selectedMenuView.setSelected(false);
2015-05-21 23:27:27 +02:00
if (parentMenu != null) {
parentMenu.onItemClick((Integer) selectedMenuView.getTag());
} else if (delegate != null) {
delegate.onItemClick((Integer) selectedMenuView.getTag());
}
2015-06-29 19:12:11 +02:00
popupWindow.dismiss(allowCloseAnimation);
} else {
popupWindow.dismiss();
}
} else {
if (selectedMenuView != null) {
selectedMenuView.setSelected(false);
selectedMenuView = null;
}
}
return super.onTouchEvent(event);
}
2015-05-21 23:27:27 +02:00
public void setDelegate(ActionBarMenuItemDelegate delegate) {
this.delegate = delegate;
2014-11-14 16:40:15 +01:00
}
2015-05-21 23:27:27 +02:00
public void setShowFromBottom(boolean value) {
showFromBottom = value;
2015-06-29 19:12:11 +02:00
if (popupLayout != null) {
popupLayout.setShowedFromBotton(showFromBottom);
}
}
2015-02-01 19:51:02 +01:00
public void setSubMenuOpenSide(int side) {
subMenuOpenSide = side;
}
2014-11-17 03:44:57 +01:00
public TextView addSubItem(int id, String text, int icon) {
if (popupLayout == null) {
rect = new Rect();
location = new int[2];
popupLayout = new ActionBarPopupWindow.ActionBarPopupWindowLayout(getContext());
popupLayout.setOnTouchListener(new OnTouchListener() {
@Override
public boolean onTouch(View v, MotionEvent event) {
if (event.getActionMasked() == MotionEvent.ACTION_DOWN) {
if (popupWindow != null && popupWindow.isShowing()) {
v.getHitRect(rect);
2015-05-21 23:27:27 +02:00
if (!rect.contains((int) event.getX(), (int) event.getY())) {
popupWindow.dismiss();
}
}
}
return false;
}
});
popupLayout.setDispatchKeyEventListener(new ActionBarPopupWindow.OnDispatchKeyEventListener() {
@Override
public void onDispatchKeyEvent(KeyEvent keyEvent) {
if (keyEvent.getKeyCode() == KeyEvent.KEYCODE_BACK && keyEvent.getRepeatCount() == 0 && popupWindow != null && popupWindow.isShowing()) {
popupWindow.dismiss();
}
}
});
}
TextView textView = new TextView(getContext());
2014-11-17 03:44:57 +01:00
textView.setTextColor(0xff212121);
textView.setBackgroundResource(R.drawable.list_selector);
2014-10-01 00:36:18 +02:00
if (!LocaleController.isRTL) {
textView.setGravity(Gravity.CENTER_VERTICAL);
} else {
textView.setGravity(Gravity.CENTER_VERTICAL | Gravity.RIGHT);
}
textView.setPadding(AndroidUtilities.dp(16), 0, AndroidUtilities.dp(16), 0);
textView.setTextSize(18);
textView.setMinWidth(AndroidUtilities.dp(196));
textView.setTag(id);
textView.setText(text);
if (icon != 0) {
textView.setCompoundDrawablePadding(AndroidUtilities.dp(12));
2014-10-01 00:36:18 +02:00
if (!LocaleController.isRTL) {
textView.setCompoundDrawablesWithIntrinsicBounds(getResources().getDrawable(icon), null, null, null);
} else {
textView.setCompoundDrawablesWithIntrinsicBounds(null, null, getResources().getDrawable(icon), null);
}
}
2015-06-29 19:12:11 +02:00
popupLayout.setShowedFromBotton(showFromBottom);
popupLayout.addView(textView);
2015-05-21 23:27:27 +02:00
LinearLayout.LayoutParams layoutParams = (LinearLayout.LayoutParams) textView.getLayoutParams();
2014-10-01 00:36:18 +02:00
if (LocaleController.isRTL) {
layoutParams.gravity = Gravity.RIGHT;
}
layoutParams.width = LayoutHelper.MATCH_PARENT;
layoutParams.height = AndroidUtilities.dp(48);
textView.setLayoutParams(layoutParams);
textView.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View view) {
2015-06-29 19:12:11 +02:00
if (popupWindow != null && popupWindow.isShowing()) {
2015-07-22 20:56:37 +02:00
if (processedPopupClick) {
return;
}
processedPopupClick = true;
2015-06-29 19:12:11 +02:00
popupWindow.dismiss(allowCloseAnimation);
}
2015-05-21 23:27:27 +02:00
if (parentMenu != null) {
parentMenu.onItemClick((Integer) view.getTag());
} else if (delegate != null) {
delegate.onItemClick((Integer) view.getTag());
}
}
});
2014-11-17 03:44:57 +01:00
menuHeight += layoutParams.height;
return textView;
}
public boolean hasSubMenu() {
return popupLayout != null;
}
public void toggleSubMenu() {
if (popupLayout == null) {
return;
}
if (showMenuRunnable != null) {
AndroidUtilities.cancelRunOnUIThread(showMenuRunnable);
showMenuRunnable = null;
}
if (popupWindow != null && popupWindow.isShowing()) {
popupWindow.dismiss();
return;
}
if (popupWindow == null) {
popupWindow = new ActionBarPopupWindow(popupLayout, LayoutHelper.WRAP_CONTENT, LayoutHelper.WRAP_CONTENT);
2015-06-29 19:12:11 +02:00
if (Build.VERSION.SDK_INT >= 19) {
popupWindow.setAnimationStyle(0);
} else {
popupWindow.setAnimationStyle(R.style.PopupAnimation);
}
popupWindow.setOutsideTouchable(true);
popupWindow.setClippingEnabled(true);
popupWindow.setInputMethodMode(ActionBarPopupWindow.INPUT_METHOD_NOT_NEEDED);
popupWindow.setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_STATE_UNSPECIFIED);
popupLayout.measure(MeasureSpec.makeMeasureSpec(AndroidUtilities.dp(1000), MeasureSpec.AT_MOST), MeasureSpec.makeMeasureSpec(AndroidUtilities.dp(1000), MeasureSpec.AT_MOST));
2014-10-01 21:55:24 +02:00
popupWindow.getContentView().setFocusableInTouchMode(true);
popupWindow.getContentView().setOnKeyListener(new OnKeyListener() {
@Override
public boolean onKey(View v, int keyCode, KeyEvent event) {
2015-05-21 23:27:27 +02:00
if (keyCode == KeyEvent.KEYCODE_MENU && event.getRepeatCount() == 0 && event.getAction() == KeyEvent.ACTION_UP && popupWindow != null && popupWindow.isShowing()) {
2014-10-01 21:55:24 +02:00
popupWindow.dismiss();
return true;
}
return false;
}
});
}
2015-07-22 20:56:37 +02:00
processedPopupClick = false;
popupWindow.setFocusable(true);
if (popupLayout.getMeasuredWidth() == 0) {
2015-06-29 19:12:11 +02:00
updateOrShowPopup(true, true);
} else {
2015-06-29 19:12:11 +02:00
updateOrShowPopup(true, false);
2014-11-17 03:44:57 +01:00
}
2015-06-29 19:12:11 +02:00
popupWindow.startAnimation();
2014-11-17 03:44:57 +01:00
}
2015-09-24 22:52:02 +02:00
public void openSearch(boolean openKeyboard) {
2015-05-21 23:27:27 +02:00
if (searchContainer == null || searchContainer.getVisibility() == VISIBLE || parentMenu == null) {
2015-01-02 23:15:07 +01:00
return;
}
2015-09-24 22:52:02 +02:00
parentMenu.parentActionBar.onSearchFieldVisibilityChanged(toggleSearch(openKeyboard));
2015-01-02 23:15:07 +01:00
}
2015-09-24 22:52:02 +02:00
public boolean toggleSearch(boolean openKeyboard) {
2015-01-02 23:15:07 +01:00
if (searchContainer == null) {
return false;
}
2015-01-02 23:15:07 +01:00
if (searchContainer.getVisibility() == VISIBLE) {
2015-06-29 19:12:11 +02:00
if (listener == null || listener != null && listener.canCollapseSearch()) {
searchContainer.setVisibility(GONE);
setVisibility(VISIBLE);
AndroidUtilities.hideKeyboard(searchField);
2015-06-29 19:12:11 +02:00
if (listener != null) {
listener.onSearchCollapse();
}
}
return false;
} else {
2015-01-02 23:15:07 +01:00
searchContainer.setVisibility(VISIBLE);
setVisibility(GONE);
searchField.setText("");
searchField.requestFocus();
2015-09-24 22:52:02 +02:00
if (openKeyboard) {
AndroidUtilities.showKeyboard(searchField);
}
if (listener != null) {
listener.onSearchExpand();
}
return true;
}
}
public void closeSubMenu() {
if (popupWindow != null && popupWindow.isShowing()) {
popupWindow.dismiss();
}
}
public void setIcon(int resId) {
iconView.setImageResource(resId);
}
public EditText getSearchField() {
return searchField;
}
public ActionBarMenuItem setIsSearchField(boolean value) {
2015-06-29 19:12:11 +02:00
return setIsSearchField(value, true);
}
2015-07-22 20:56:37 +02:00
public ActionBarMenuItem setOverrideMenuClick(boolean value) {
overrideMenuClick = value;
return this;
}
2015-06-29 19:12:11 +02:00
public ActionBarMenuItem setIsSearchField(boolean value, boolean needClearButton) {
2015-05-21 23:27:27 +02:00
if (parentMenu == null) {
return this;
}
2015-01-02 23:15:07 +01:00
if (value && searchContainer == null) {
searchContainer = new FrameLayout(getContext());
parentMenu.addView(searchContainer, 0);
2015-05-21 23:27:27 +02:00
LinearLayout.LayoutParams layoutParams = (LinearLayout.LayoutParams) searchContainer.getLayoutParams();
2015-01-02 23:15:07 +01:00
layoutParams.weight = 1;
layoutParams.width = 0;
layoutParams.height = LayoutHelper.MATCH_PARENT;
2015-01-02 23:15:07 +01:00
layoutParams.leftMargin = AndroidUtilities.dp(6);
searchContainer.setLayoutParams(layoutParams);
searchContainer.setVisibility(GONE);
searchField = new EditText(getContext());
2015-01-02 23:15:07 +01:00
searchField.setTextSize(TypedValue.COMPLEX_UNIT_DIP, 18);
searchField.setHintTextColor(0x88ffffff);
searchField.setTextColor(0xffffffff);
searchField.setSingleLine(true);
2015-01-02 23:15:07 +01:00
searchField.setBackgroundResource(0);
2014-11-14 16:40:15 +01:00
searchField.setPadding(0, 0, 0, 0);
2015-07-22 20:56:37 +02:00
int inputType = searchField.getInputType() | EditorInfo.TYPE_TEXT_FLAG_NO_SUGGESTIONS;
searchField.setInputType(inputType);
if (android.os.Build.VERSION.SDK_INT < 11) {
searchField.setOnCreateContextMenuListener(new OnCreateContextMenuListener() {
public void onCreateContextMenu(ContextMenu menu, View v, ContextMenu.ContextMenuInfo menuInfo) {
menu.clear();
}
});
} else {
searchField.setCustomSelectionActionModeCallback(new ActionMode.Callback() {
public boolean onPrepareActionMode(ActionMode mode, Menu menu) {
return false;
}
public void onDestroyActionMode(ActionMode mode) {
2015-06-29 19:12:11 +02:00
}
public boolean onCreateActionMode(ActionMode mode, Menu menu) {
return false;
}
public boolean onActionItemClicked(ActionMode mode, MenuItem item) {
return false;
}
});
}
searchField.setOnEditorActionListener(new TextView.OnEditorActionListener() {
@Override
public boolean onEditorAction(TextView v, int actionId, KeyEvent event) {
if (/*actionId == EditorInfo.IME_ACTION_SEARCH || */event != null && (event.getAction() == KeyEvent.ACTION_UP && event.getKeyCode() == KeyEvent.KEYCODE_SEARCH || event.getAction() == KeyEvent.ACTION_DOWN && event.getKeyCode() == KeyEvent.KEYCODE_ENTER)) {
AndroidUtilities.hideKeyboard(searchField);
2015-01-02 23:15:07 +01:00
if (listener != null) {
listener.onSearchPressed(searchField);
}
}
return false;
}
});
searchField.addTextChangedListener(new TextWatcher() {
@Override
public void beforeTextChanged(CharSequence s, int start, int count, int after) {
}
@Override
public void onTextChanged(CharSequence s, int start, int before, int count) {
if (listener != null) {
listener.onTextChanged(searchField);
}
2015-06-29 19:12:11 +02:00
if (clearButton != null) {
ViewProxy.setAlpha(clearButton, s == null || s.length() == 0 ? 0.6f : 1.0f);
}
}
@Override
public void afterTextChanged(Editable s) {
}
});
try {
Field mCursorDrawableRes = TextView.class.getDeclaredField("mCursorDrawableRes");
mCursorDrawableRes.setAccessible(true);
mCursorDrawableRes.set(searchField, R.drawable.search_carret);
} catch (Exception e) {
//nothing to do
}
if (Build.VERSION.SDK_INT >= 11) {
searchField.setImeOptions(EditorInfo.IME_FLAG_NO_FULLSCREEN | EditorInfo.IME_ACTION_SEARCH);
searchField.setTextIsSelectable(false);
} else {
searchField.setImeOptions(EditorInfo.IME_ACTION_SEARCH);
}
2015-01-02 23:15:07 +01:00
searchContainer.addView(searchField);
FrameLayout.LayoutParams layoutParams2 = (FrameLayout.LayoutParams) searchField.getLayoutParams();
layoutParams2.width = LayoutHelper.MATCH_PARENT;
2015-01-02 23:15:07 +01:00
layoutParams2.gravity = Gravity.CENTER_VERTICAL;
layoutParams2.height = AndroidUtilities.dp(36);
2015-07-22 20:56:37 +02:00
layoutParams2.rightMargin = needClearButton ? AndroidUtilities.dp(48) : 0;
2015-01-02 23:15:07 +01:00
searchField.setLayoutParams(layoutParams2);
2015-06-29 19:12:11 +02:00
if (needClearButton) {
clearButton = new ImageView(getContext());
clearButton.setImageResource(R.drawable.ic_close_white);
clearButton.setScaleType(ImageView.ScaleType.CENTER);
clearButton.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
searchField.setText("");
AndroidUtilities.showKeyboard(searchField);
}
});
searchContainer.addView(clearButton);
layoutParams2 = (FrameLayout.LayoutParams) clearButton.getLayoutParams();
layoutParams2.width = AndroidUtilities.dp(48);
layoutParams2.gravity = Gravity.CENTER_VERTICAL | Gravity.RIGHT;
layoutParams2.height = LayoutHelper.MATCH_PARENT;
clearButton.setLayoutParams(layoutParams2);
}
}
isSearchField = value;
return this;
}
public boolean isSearchField() {
return isSearchField;
}
2015-01-02 23:15:07 +01:00
public ActionBarMenuItem setActionBarMenuItemSearchListener(ActionBarMenuItemSearchListener listener) {
this.listener = listener;
2015-01-02 23:15:07 +01:00
return this;
}
2015-06-29 19:12:11 +02:00
public ActionBarMenuItem setAllowCloseAnimation(boolean value) {
allowCloseAnimation = value;
return this;
}
@Override
protected void onLayout(boolean changed, int left, int top, int right, int bottom) {
super.onLayout(changed, left, top, right, bottom);
if (popupWindow != null && popupWindow.isShowing()) {
2015-06-29 19:12:11 +02:00
updateOrShowPopup(false, true);
}
}
private void updateOrShowPopup(boolean show, boolean update) {
int offsetY;
if (showFromBottom) {
getLocationOnScreen(location);
int diff = location[1] - AndroidUtilities.statusBarHeight + getMeasuredHeight() - menuHeight;
offsetY = -menuHeight;
if (diff < 0) {
offsetY -= diff;
}
} else {
if (parentMenu != null && subMenuOpenSide == 0) {
offsetY = -parentMenu.parentActionBar.getMeasuredHeight() + parentMenu.getTop();
} else {
offsetY = -getMeasuredHeight();
}
}
2015-07-22 20:56:37 +02:00
if (show) {
popupLayout.scrollToTop();
}
2015-06-29 19:12:11 +02:00
if (subMenuOpenSide == 0) {
if (showFromBottom) {
if (show) {
popupWindow.showAsDropDown(this, -popupLayout.getMeasuredWidth() + getMeasuredWidth(), offsetY);
}
if (update) {
popupWindow.update(this, -popupLayout.getMeasuredWidth() + getMeasuredWidth(), offsetY, -1, -1);
2015-02-01 19:51:02 +01:00
}
2014-11-14 16:40:15 +01:00
} else {
2015-06-29 19:12:11 +02:00
if (parentMenu != null) {
View parent = parentMenu.parentActionBar;
if (show) {
popupWindow.showAsDropDown(parent, getLeft() + parentMenu.getLeft() + getMeasuredWidth() - popupLayout.getMeasuredWidth(), offsetY);
}
if (update) {
popupWindow.update(parent, getLeft() + parentMenu.getLeft() + getMeasuredWidth() - popupLayout.getMeasuredWidth(), offsetY, -1, -1);
}
} else if (getParent() != null) {
View parent = (View) getParent();
if (show) {
popupWindow.showAsDropDown(parent, parent.getMeasuredWidth() - popupLayout.getMeasuredWidth() - getLeft() - parent.getLeft(), offsetY);
}
if (update) {
popupWindow.update(parent, parent.getMeasuredWidth() - popupLayout.getMeasuredWidth() - getLeft() - parent.getLeft(), offsetY, -1, -1);
}
}
}
} else {
if (show) {
popupWindow.showAsDropDown(this, -AndroidUtilities.dp(8), offsetY);
}
if (update) {
popupWindow.update(this, -AndroidUtilities.dp(8), offsetY, -1, -1);
2014-11-14 16:40:15 +01:00
}
}
}
public void hideSubItem(int id) {
View view = popupLayout.findViewWithTag(id);
if (view != null) {
view.setVisibility(GONE);
}
}
public void showSubItem(int id) {
View view = popupLayout.findViewWithTag(id);
if (view != null) {
view.setVisibility(VISIBLE);
}
}
}