diff options
author | Scott Jackson <daneren2005@gmail.com> | 2014-04-26 17:03:13 -0700 |
---|---|---|
committer | Scott Jackson <daneren2005@gmail.com> | 2014-04-26 17:03:13 -0700 |
commit | 9eb67ba4dc384dfad8496f24d5288df619a0d8fd (patch) | |
tree | 8f8ca0e369c325b97027ffd1a2a5c5a381281efa /src/github/daneren2005 | |
parent | 71785e9ce8b6d9edea43f4f9bdb76e725c0772ca (diff) | |
parent | 0be9df3ac3e66c806705c5312910be17007bacb2 (diff) | |
download | dsub-9eb67ba4dc384dfad8496f24d5288df619a0d8fd.tar.gz dsub-9eb67ba4dc384dfad8496f24d5288df619a0d8fd.tar.bz2 dsub-9eb67ba4dc384dfad8496f24d5288df619a0d8fd.zip |
Merge branch 'Grid' of https://github.com/daneren2005/Subsonic
Diffstat (limited to 'src/github/daneren2005')
8 files changed, 329 insertions, 148 deletions
diff --git a/src/github/daneren2005/dsub/fragments/SelectDirectoryFragment.java b/src/github/daneren2005/dsub/fragments/SelectDirectoryFragment.java index 1479d4cd..34be2d8c 100644 --- a/src/github/daneren2005/dsub/fragments/SelectDirectoryFragment.java +++ b/src/github/daneren2005/dsub/fragments/SelectDirectoryFragment.java @@ -17,6 +17,7 @@ import android.view.View; import android.view.ViewGroup;
import android.widget.AbsListView;
import android.widget.AdapterView;
+import android.widget.GridView;
import android.widget.ImageView;
import android.widget.ListView;
import android.widget.TextView;
@@ -24,6 +25,7 @@ import github.daneren2005.dsub.R; import github.daneren2005.dsub.domain.MusicDirectory;
import github.daneren2005.dsub.domain.Share;
import github.daneren2005.dsub.util.ImageLoader;
+import github.daneren2005.dsub.view.AlbumGridAdapter;
import github.daneren2005.dsub.view.EntryAdapter;
import java.io.Serializable;
@@ -50,13 +52,16 @@ import java.util.Set; public class SelectDirectoryFragment extends SubsonicFragment implements AdapterView.OnItemClickListener {
private static final String TAG = SelectDirectoryFragment.class.getSimpleName();
- private DragSortListView entryList;
+ private GridView albumList;
+ private ListView entryList;
private View emptyView;
private boolean hideButtons = false;
private Boolean licenseValid;
private boolean showHeader = true;
private EntryAdapter entryAdapter;
+ private List<MusicDirectory.Entry> albums;
private List<MusicDirectory.Entry> entries;
+ private boolean albumContext = false;
String id;
String name;
@@ -99,23 +104,9 @@ public class SelectDirectoryFragment extends SubsonicFragment implements Adapter refreshLayout = (SwipeRefreshLayout) rootView.findViewById(R.id.refresh_layout);
refreshLayout.setOnRefreshListener(this);
- entryList = (DragSortListView) rootView.findViewById(R.id.select_album_entries);
+ entryList = (ListView) rootView.findViewById(R.id.select_album_entries);
entryList.setChoiceMode(ListView.CHOICE_MODE_MULTIPLE);
entryList.setOnItemClickListener(this);
- entryList.setDropListener(new DragSortListView.DropListener() {
- @Override
- public void drop(int from, int to) {
- int max = entries.size();
- if(to >= max) {
- to = max - 1;
- }
- else if(to < 0) {
- to = 0;
- }
- entries.add(to, entries.remove(from));
- entryAdapter.notifyDataSetChanged();
- }
- });
entryList.setOnScrollListener(new AbsListView.OnScrollListener() {
@Override
@@ -128,9 +119,32 @@ public class SelectDirectoryFragment extends SubsonicFragment implements Adapter }
});
+ albumList = (GridView) inflater.inflate(R.layout.grid_view, entryList, false);
+ albumList.setOnItemClickListener(new AdapterView.OnItemClickListener() {
+ @Override
+ public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
+ MusicDirectory.Entry entry = (MusicDirectory.Entry) parent.getItemAtPosition(position);
+ SubsonicFragment fragment = new SelectDirectoryFragment();
+ Bundle args = new Bundle();
+ args.putString(Constants.INTENT_EXTRA_NAME_ID, entry.getId());
+ args.putString(Constants.INTENT_EXTRA_NAME_NAME, entry.getTitle());
+ if ("newest".equals(albumListType)) {
+ args.putBoolean(Constants.INTENT_EXTRA_REFRESH_LISTINGS, true);
+ }
+ if(entry.getArtist() == null && entry.getParent() == null) {
+ args.putBoolean(Constants.INTENT_EXTRA_NAME_ARTIST, true);
+ }
+ fragment.setArguments(args);
+
+ replaceFragment(fragment, true);
+ }
+ });
+ entryList.addHeaderView(albumList);
+
emptyView = rootView.findViewById(R.id.select_album_empty);
registerForContextMenu(entryList);
+ registerForContextMenu(albumList);
Bundle args = getArguments();
if(args != null) {
@@ -284,7 +298,18 @@ public class SelectDirectoryFragment extends SubsonicFragment implements Adapter AdapterView.AdapterContextMenuInfo info = (AdapterView.AdapterContextMenuInfo) menuInfo;
- MusicDirectory.Entry entry = (MusicDirectory.Entry) entryList.getItemAtPosition(info.position);
+ MusicDirectory.Entry entry;
+ if(view.getId() == R.id.select_album_entries) {
+ if(info.position == 0) {
+ return;
+ }
+ entry = (MusicDirectory.Entry) entryList.getItemAtPosition(info.position);
+ albumContext = false;
+ } else {
+ entry = (MusicDirectory.Entry) albumList.getItemAtPosition(info.position);
+ albumContext = true;
+ }
+
onCreateContextMenu(menu, view, menuInfo, entry);
if(!entry.isVideo() && !Util.isOffline(context) && playlistId == null && (podcastId == null || Util.isOffline(context) && podcastId != null)) {
menu.removeItem(R.id.song_menu_remove_playlist);
@@ -310,7 +335,16 @@ public class SelectDirectoryFragment extends SubsonicFragment implements Adapter }
AdapterView.AdapterContextMenuInfo info = (AdapterView.AdapterContextMenuInfo) menuItem.getMenuInfo();
- Object selectedItem = entries.get(showHeader ? (info.position - 1) : info.position);
+ Object selectedItem;
+ if(albumContext) {
+ selectedItem = albums.get(showHeader ? (info.position - 1) : info.position);
+ } else {
+ if(info.position == 0) {
+ return false;
+ }
+ info.position--;
+ selectedItem = entries.get(showHeader ? (info.position - 1) : info.position);
+ }
if(Util.getPreferences(context).getBoolean(Constants.PREFERENCES_KEY_PLAY_NOW_AFTER, false) && menuItem.getItemId() == R.id.song_menu_play_now) {
List<MusicDirectory.Entry> songs = new ArrayList<MusicDirectory.Entry>();
@@ -575,7 +609,8 @@ public class SelectDirectoryFragment extends SubsonicFragment implements Adapter @Override
protected void done(Pair<MusicDirectory, Boolean> result) {
- entries = result.getFirst().getChildren();
+ albums = result.getFirst().getChildren(true, false);
+ entries = result.getFirst().getChildren(false, true);
licenseValid = result.getSecond();
finishLoading();
}
@@ -593,7 +628,9 @@ public class SelectDirectoryFragment extends SubsonicFragment implements Adapter if(showHeader) {
View header = createHeader(entries);
if(header != null) {
+ entryList.removeHeaderView(albumList);
entryList.addHeaderView(header, null, false);
+ entryList.addHeaderView(albumList);
}
}
} else {
@@ -603,13 +640,14 @@ public class SelectDirectoryFragment extends SubsonicFragment implements Adapter }
}
- emptyView.setVisibility(entries.isEmpty() ? View.VISIBLE : View.GONE);
- entryAdapter = new EntryAdapter(context, getImageLoader(), entries, (podcastId == null));
- if(albumListType == null || "starred".equals(albumListType)) {
- entryList.setAdapter(entryAdapter);
- } else {
- entryList.setAdapter(new AlbumListAdapter(context, entryAdapter, albumListType, albumListExtra, albumListSize));
- }
+ emptyView.setVisibility((entries.isEmpty() && albums.isEmpty()) ? View.VISIBLE : View.GONE);
+ entryAdapter = new EntryAdapter(context, getImageLoader(), entries, (podcastId == null));
+ entryList.setAdapter(entryAdapter);
+ if(albumListType == null || "starred".equals(albumListType)) {
+ albumList.setAdapter(new AlbumGridAdapter(context, getImageLoader(), albums));
+ } else {
+ albumList.setAdapter(new AlbumListAdapter(context, new AlbumGridAdapter(context, getImageLoader(), albums), albumListType, albumListExtra, albumListSize));
+ }
entryList.setVisibility(View.VISIBLE);
context.supportInvalidateOptionsMenu();
diff --git a/src/github/daneren2005/dsub/view/AlbumCell.java b/src/github/daneren2005/dsub/view/AlbumCell.java new file mode 100644 index 00000000..9cee0c41 --- /dev/null +++ b/src/github/daneren2005/dsub/view/AlbumCell.java @@ -0,0 +1,88 @@ +/*
+ This file is part of Subsonic.
+ Subsonic is free software: you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+ Subsonic is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+ You should have received a copy of the GNU General Public License
+ along with Subsonic. If not, see <http://www.gnu.org/licenses/>.
+ Copyright 2014 (C) Scott Jackson
+*/
+
+package github.daneren2005.dsub.view;
+
+import android.content.Context;
+import android.view.LayoutInflater;
+import android.view.View;
+import android.widget.ImageButton;
+import android.widget.ImageView;
+import android.widget.TextView;
+
+import java.io.File;
+
+import github.daneren2005.dsub.R;
+import github.daneren2005.dsub.domain.MusicDirectory;
+import github.daneren2005.dsub.util.FileUtil;
+import github.daneren2005.dsub.util.ImageLoader;
+
+public class AlbumCell extends UpdateView {
+ private static final String TAG = AlbumCell.class.getSimpleName();
+
+ private Context context;
+ private MusicDirectory.Entry album;
+ private File file;
+
+ private View coverArtView;
+ private TextView titleView;
+ private TextView artistView;
+
+ public AlbumCell(Context context) {
+ super(context);
+ this.context = context;
+ LayoutInflater.from(context).inflate(R.layout.album_cell_item, this, true);
+
+ coverArtView = findViewById(R.id.album_coverart);
+ titleView = (TextView) findViewById(R.id.album_title);
+ artistView = (TextView) findViewById(R.id.album_artist);
+ moreButton = (ImageView) findViewById(R.id.album_more);
+ moreButton.setOnClickListener(new View.OnClickListener() {
+ public void onClick(View v) {
+ v.showContextMenu();
+ }
+ });
+ }
+
+ protected void setObjectImpl(Object obj1, Object obj2) {
+ this.album = (MusicDirectory.Entry) obj1;
+ if(album.getAlbum() == null) {
+ titleView.setText(album.getTitle());
+ } else {
+ titleView.setText(album.getAlbum());
+ }
+ String artist = album.getArtist();
+ if(artist == null) {
+ artist = "";
+ }
+ if(album.getYear() != null) {
+ artist += " - " + album.getYear();
+ }
+ artistView.setText(artist);
+ artistView.setVisibility(album.getArtist() == null ? View.GONE : View.VISIBLE);
+ ((ImageLoader)obj2).loadImage(coverArtView, album, false, true);
+ file = null;
+ }
+
+ @Override
+ protected void updateBackground() {
+ if(file == null) {
+ file = FileUtil.getAlbumDirectory(context, album);
+ }
+
+ exists = file.exists();
+ isStarred = album.isStarred();
+ }
+}
diff --git a/src/github/daneren2005/dsub/view/AlbumGridAdapter.java b/src/github/daneren2005/dsub/view/AlbumGridAdapter.java new file mode 100644 index 00000000..3c81fa9a --- /dev/null +++ b/src/github/daneren2005/dsub/view/AlbumGridAdapter.java @@ -0,0 +1,55 @@ +/*
+ This file is part of Subsonic.
+ Subsonic is free software: you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+ Subsonic is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+ You should have received a copy of the GNU General Public License
+ along with Subsonic. If not, see <http://www.gnu.org/licenses/>.
+ Copyright 2014 (C) Scott Jackson
+*/
+
+package github.daneren2005.dsub.view;
+
+import android.content.Context;
+import android.view.View;
+import android.view.ViewGroup;
+import android.widget.ArrayAdapter;
+
+import java.util.List;
+
+import github.daneren2005.dsub.domain.MusicDirectory;
+import github.daneren2005.dsub.util.ImageLoader;
+
+public class AlbumGridAdapter extends ArrayAdapter<MusicDirectory.Entry> {
+ private final static String TAG = AlbumGridAdapter.class.getSimpleName();
+ private final Context activity;
+ private final ImageLoader imageLoader;
+ private List<MusicDirectory.Entry> entries;
+
+ public AlbumGridAdapter(Context activity, ImageLoader imageLoader, List<MusicDirectory.Entry> entries) {
+ super(activity, android.R.layout.simple_list_item_1, entries);
+ this.entries = entries;
+ this.activity = activity;
+ this.imageLoader = imageLoader;
+ }
+
+ @Override
+ public View getView(int position, View convertView, ViewGroup parent) {
+ MusicDirectory.Entry entry = getItem(position);
+
+ AlbumCell view;
+ if(convertView instanceof AlbumCell) {
+ view = (AlbumCell) convertView;
+ } else {
+ view = new AlbumCell(activity);
+ }
+
+ view.setObject(entry, imageLoader);
+ return view;
+ }
+}
diff --git a/src/github/daneren2005/dsub/view/AlbumView.java b/src/github/daneren2005/dsub/view/AlbumView.java deleted file mode 100644 index be13aa5c..00000000 --- a/src/github/daneren2005/dsub/view/AlbumView.java +++ /dev/null @@ -1,100 +0,0 @@ -/* - This file is part of Subsonic. - - Subsonic is free software: you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - Subsonic is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with Subsonic. If not, see <http://www.gnu.org/licenses/>. - - Copyright 2009 (C) Sindre Mehus - */ -package github.daneren2005.dsub.view; - -import android.content.Context; -import android.util.Log; -import android.view.LayoutInflater; -import android.view.View; -import android.widget.ImageButton; -import android.widget.ImageView; -import android.widget.TextView; -import github.daneren2005.dsub.R; -import github.daneren2005.dsub.domain.MusicDirectory; -import github.daneren2005.dsub.util.FileUtil; -import github.daneren2005.dsub.util.ImageLoader; -import github.daneren2005.dsub.util.Util; -import java.io.File; -import java.util.List; - -/** - * Used to display albums in a {@code ListView}. - * - * @author Sindre Mehus - */ -public class AlbumView extends UpdateView { - private static final String TAG = AlbumView.class.getSimpleName(); - - private Context context; - private MusicDirectory.Entry album; - private File file; - - private TextView titleView; - private TextView artistView; - private View coverArtView; - - public AlbumView(Context context) { - super(context); - this.context = context; - LayoutInflater.from(context).inflate(R.layout.album_list_item, this, true); - - titleView = (TextView) findViewById(R.id.album_title); - artistView = (TextView) findViewById(R.id.album_artist); - coverArtView = findViewById(R.id.album_coverart); - starButton = (ImageButton) findViewById(R.id.album_star); - starButton.setFocusable(false); - - moreButton = (ImageView) findViewById(R.id.album_more); - moreButton.setOnClickListener(new View.OnClickListener() { - public void onClick(View v) { - v.showContextMenu(); - } - }); - } - - protected void setObjectImpl(Object obj1, Object obj2) { - this.album = (MusicDirectory.Entry) obj1; - if(album.getAlbum() == null) { - titleView.setText(album.getTitle()); - } else { - titleView.setText(album.getAlbum()); - } - String artist = album.getArtist(); - if(artist == null) { - artist = ""; - } - if(album.getYear() != null) { - artist += " - " + album.getYear(); - } - artistView.setText(artist); - artistView.setVisibility(album.getArtist() == null ? View.GONE : View.VISIBLE); - ((ImageLoader)obj2).loadImage(coverArtView, album, false, true); - file = null; - } - - @Override - protected void updateBackground() { - if(file == null) { - file = FileUtil.getAlbumDirectory(context, album); - } - - exists = file.exists(); - isStarred = album.isStarred(); - } -} diff --git a/src/github/daneren2005/dsub/view/ArtistEntryView.java b/src/github/daneren2005/dsub/view/ArtistEntryView.java index 958b4b87..86fe7b1f 100644 --- a/src/github/daneren2005/dsub/view/ArtistEntryView.java +++ b/src/github/daneren2005/dsub/view/ArtistEntryView.java @@ -37,7 +37,7 @@ import java.io.File; * @author Sindre Mehus
*/
public class ArtistEntryView extends UpdateView {
- private static final String TAG = AlbumView.class.getSimpleName();
+ private static final String TAG = ArtistEntryView.class.getSimpleName();
private Context context;
private MusicDirectory.Entry artist;
diff --git a/src/github/daneren2005/dsub/view/EntryAdapter.java b/src/github/daneren2005/dsub/view/EntryAdapter.java index 4fa5cdf0..7da6e5a1 100644 --- a/src/github/daneren2005/dsub/view/EntryAdapter.java +++ b/src/github/daneren2005/dsub/view/EntryAdapter.java @@ -54,26 +54,13 @@ public class EntryAdapter extends ArrayAdapter<MusicDirectory.Entry> { public View getView(int position, View convertView, ViewGroup parent) { MusicDirectory.Entry entry = getItem(position); - if (entry.isDirectory()) { - if(entry.getArtist() != null || entry.getParent() != null) { - AlbumView view; - view = new AlbumView(activity); - view.setObject(entry, imageLoader); - return view; - } else { - ArtistEntryView view = new ArtistEntryView(activity); - view.setObject(entry); - return view; - } - } else { - SongView view; - if (convertView != null && convertView instanceof SongView) { - view = (SongView) convertView; - } else { - view = new SongView(activity); - } - view.setObject(entry, checkable); - return view; - } + SongView view; + if (convertView != null && convertView instanceof SongView) { + view = (SongView) convertView; + } else { + view = new SongView(activity); + } + view.setObject(entry, checkable); + return view; } } diff --git a/src/github/daneren2005/dsub/view/SquareImageView.java b/src/github/daneren2005/dsub/view/SquareImageView.java new file mode 100644 index 00000000..77ca50db --- /dev/null +++ b/src/github/daneren2005/dsub/view/SquareImageView.java @@ -0,0 +1,32 @@ +/*
+ This file is part of Subsonic.
+ Subsonic is free software: you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+ Subsonic is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+ You should have received a copy of the GNU General Public License
+ along with Subsonic. If not, see <http://www.gnu.org/licenses/>.
+ Copyright 2014 (C) Scott Jackson
+*/
+
+package github.daneren2005.dsub.view;
+
+import android.content.Context;
+import android.util.AttributeSet;
+import android.widget.ImageView;
+
+public class SquareImageView extends ImageView {
+ public SquareImageView(final Context context, final AttributeSet attrs) {
+ super(context, attrs);
+ }
+
+ @Override
+ public void onMeasure(final int widthSpec, final int heightSpec) {
+ super.onMeasure(widthSpec, heightSpec);
+ setMeasuredDimension(getMeasuredWidth(), getMeasuredWidth());
+ }
+}
diff --git a/src/github/daneren2005/dsub/view/UnscrollableGridView.java b/src/github/daneren2005/dsub/view/UnscrollableGridView.java new file mode 100644 index 00000000..a36a7b79 --- /dev/null +++ b/src/github/daneren2005/dsub/view/UnscrollableGridView.java @@ -0,0 +1,81 @@ +package github.daneren2005.dsub.view;
+
+import android.content.Context;
+import android.util.AttributeSet;
+import android.view.View;
+import android.widget.AbsListView;
+import android.widget.GridView;
+import android.widget.ListAdapter;
+
+/**
+ * Created by Scott on 4/26/2014.
+ */
+public class UnscrollableGridView extends GridView {
+ public UnscrollableGridView(Context context) {
+ super(context);
+ }
+
+ public UnscrollableGridView(Context context, AttributeSet attrs) {
+ super(context, attrs);
+ }
+
+ public UnscrollableGridView(Context context, AttributeSet attrs, int defStyle) {
+ super(context, attrs, defStyle);
+ }
+
+ @Override
+ public int getColumnWidth() {
+ // This method will be called from onMeasure() too.
+ // It's better to use getMeasuredWidth(), as it is safe in this case.
+ final int totalHorizontalSpacing = getNumColumns() > 0 ? (getNumColumns() - 1) * getHorizontalSpacing() : 0;
+ return (getMeasuredWidth() - getPaddingLeft() - getPaddingRight() - totalHorizontalSpacing) / getNumColumns();
+ }
+
+ @Override
+ protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
+ // Sets the padding for this view.
+ super.onMeasure(widthMeasureSpec, heightMeasureSpec);
+
+ final int measuredWidth = getMeasuredWidth();
+ final int childWidth = getColumnWidth();
+ int childHeight = 0;
+
+ // If there's an adapter, use it to calculate the height of this view.
+ final ListAdapter adapter = getAdapter();
+ final int count;
+
+ // There shouldn't be any inherent size (due to padding) if there are no child views.
+ if (adapter == null || (count = adapter.getCount()) == 0) {
+ setMeasuredDimension(0, 0);
+ return;
+ }
+
+ // Get the first child from the adapter.
+ final View child = adapter.getView(0, null, this);
+ if (child != null) {
+ // Set a default LayoutParams on the child, if it doesn't have one on its own.
+ AbsListView.LayoutParams params = (AbsListView.LayoutParams) child.getLayoutParams();
+ if (params == null) {
+ params = new AbsListView.LayoutParams(AbsListView.LayoutParams.WRAP_CONTENT,
+ AbsListView.LayoutParams.WRAP_CONTENT);
+ child.setLayoutParams(params);
+ }
+
+ // Measure the exact width of the child, and the height based on the width.
+ // Note: the child takes care of calculating its height.
+ int childWidthSpec = MeasureSpec.makeMeasureSpec(childWidth, MeasureSpec.EXACTLY);
+ int childHeightSpec = MeasureSpec.makeMeasureSpec(0, MeasureSpec.UNSPECIFIED);
+ child.measure(childWidthSpec, childHeightSpec);
+ childHeight = child.getMeasuredHeight();
+ }
+
+ // Number of rows required to 'mTotal' items.
+ final int rows = (int) Math.ceil((double) getCount() / getNumColumns());
+ final int childrenHeight = childHeight * rows;
+ final int totalVerticalSpacing = rows > 0 ? (rows - 1) * getVerticalSpacing() : 0;
+
+ // Total height of this view.
+ final int measuredHeight = childrenHeight + getPaddingTop() + getPaddingBottom() + totalVerticalSpacing;
+ setMeasuredDimension(measuredWidth, measuredHeight);
+ }
+}
|