Merge remote-tracking branch 'origin/master'

This commit is contained in:
Weblate 2015-10-08 16:51:59 +02:00
commit eaa32c4060
19 changed files with 6780 additions and 50 deletions

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,37 @@
/*
* Copyright 2012 Google Inc. All Rights Reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.googlecode.concurrentlinkedhashmap;
/**
* A class that can determine the weight of an entry. The total weight threshold
* is used to determine when an eviction is required.
*
* @author ben.manes@gmail.com (Ben Manes)
* @see <a href="http://code.google.com/p/concurrentlinkedhashmap/">
* http://code.google.com/p/concurrentlinkedhashmap/</a>
*/
public interface EntryWeigher<K, V> {
/**
* Measures an entry's weight to determine how many units of capacity that
* the key and value consumes. An entry must consume a minimum of one unit.
*
* @param key the key to weigh
* @param value the value to weigh
* @return the entry's weight
*/
int weightOf(K key, V value);
}

View file

@ -0,0 +1,45 @@
/*
* Copyright 2010 Google Inc. All Rights Reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.googlecode.concurrentlinkedhashmap;
/**
* A listener registered for notification when an entry is evicted. An instance
* may be called concurrently by multiple threads to process entries. An
* implementation should avoid performing blocking calls or synchronizing on
* shared resources.
* <p>
* The listener is invoked by {@link ConcurrentLinkedHashMap} on a caller's
* thread and will not block other threads from operating on the map. An
* implementation should be aware that the caller's thread will not expect
* long execution times or failures as a side effect of the listener being
* notified. Execution safety and a fast turn around time can be achieved by
* performing the operation asynchronously, such as by submitting a task to an
* {@link java.util.concurrent.ExecutorService}.
*
* @author ben.manes@gmail.com (Ben Manes)
* @see <a href="http://code.google.com/p/concurrentlinkedhashmap/">
* http://code.google.com/p/concurrentlinkedhashmap/</a>
*/
public interface EvictionListener<K, V> {
/**
* A call-back notification that the entry was evicted.
*
* @param key the entry's key
* @param value the entry's value
*/
void onEviction(K key, V value);
}

View file

@ -0,0 +1,460 @@
/*
* Copyright 2011 Google Inc. All Rights Reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.googlecode.concurrentlinkedhashmap;
import java.util.AbstractCollection;
import java.util.Collection;
import java.util.Deque;
import java.util.Iterator;
import java.util.NoSuchElementException;
/**
* Linked list implementation of the {@link Deque} interface where the link
* pointers are tightly integrated with the element. Linked deques have no
* capacity restrictions; they grow as necessary to support usage. They are not
* thread-safe; in the absence of external synchronization, they do not support
* concurrent access by multiple threads. Null elements are prohibited.
* <p>
* Most <tt>LinkedDeque</tt> operations run in constant time by assuming that
* the {@link Linked} parameter is associated with the deque instance. Any usage
* that violates this assumption will result in non-deterministic behavior.
* <p>
* The iterators returned by this class are <em>not</em> <i>fail-fast</i>: If
* the deque is modified at any time after the iterator is created, the iterator
* will be in an unknown state. Thus, in the face of concurrent modification,
* the iterator risks arbitrary, non-deterministic behavior at an undetermined
* time in the future.
*
* @author ben.manes@gmail.com (Ben Manes)
* @param <E> the type of elements held in this collection
* @see <a href="http://code.google.com/p/concurrentlinkedhashmap/">
* http://code.google.com/p/concurrentlinkedhashmap/</a>
*/
final class LinkedDeque<E extends Linked<E>> extends AbstractCollection<E> implements Deque<E> {
// This class provides a doubly-linked list that is optimized for the virtual
// machine. The first and last elements are manipulated instead of a slightly
// more convenient sentinel element to avoid the insertion of null checks with
// NullPointerException throws in the byte code. The links to a removed
// element are cleared to help a generational garbage collector if the
// discarded elements inhabit more than one generation.
/**
* Pointer to first node.
* Invariant: (first == null && last == null) ||
* (first.prev == null)
*/
E first;
/**
* Pointer to last node.
* Invariant: (first == null && last == null) ||
* (last.next == null)
*/
E last;
/**
* Links the element to the front of the deque so that it becomes the first
* element.
*
* @param e the unlinked element
*/
void linkFirst(final E e) {
final E f = first;
first = e;
if (f == null) {
last = e;
} else {
f.setPrevious(e);
e.setNext(f);
}
}
/**
* Links the element to the back of the deque so that it becomes the last
* element.
*
* @param e the unlinked element
*/
void linkLast(final E e) {
final E l = last;
last = e;
if (l == null) {
first = e;
} else {
l.setNext(e);
e.setPrevious(l);
}
}
/** Unlinks the non-null first element. */
E unlinkFirst() {
final E f = first;
final E next = f.getNext();
f.setNext(null);
first = next;
if (next == null) {
last = null;
} else {
next.setPrevious(null);
}
return f;
}
/** Unlinks the non-null last element. */
E unlinkLast() {
final E l = last;
final E prev = l.getPrevious();
l.setPrevious(null);
last = prev;
if (prev == null) {
first = null;
} else {
prev.setNext(null);
}
return l;
}
/** Unlinks the non-null element. */
void unlink(E e) {
final E prev = e.getPrevious();
final E next = e.getNext();
if (prev == null) {
first = next;
} else {
prev.setNext(next);
e.setPrevious(null);
}
if (next == null) {
last = prev;
} else {
next.setPrevious(prev);
e.setNext(null);
}
}
@Override
public boolean isEmpty() {
return (first == null);
}
void checkNotEmpty() {
if (isEmpty()) {
throw new NoSuchElementException();
}
}
/**
* {@inheritDoc}
* <p>
* Beware that, unlike in most collections, this method is <em>NOT</em> a
* constant-time operation.
*/
@Override
public int size() {
int size = 0;
for (E e = first; e != null; e = e.getNext()) {
size++;
}
return size;
}
@Override
public void clear() {
for (E e = first; e != null;) {
E next = e.getNext();
e.setPrevious(null);
e.setNext(null);
e = next;
}
first = last = null;
}
@Override
public boolean contains(Object o) {
return (o instanceof Linked<?>) && contains((Linked<?>) o);
}
// A fast-path containment check
boolean contains(Linked<?> e) {
return (e.getPrevious() != null)
|| (e.getNext() != null)
|| (e == first);
}
/**
* Moves the element to the front of the deque so that it becomes the first
* element.
*
* @param e the linked element
*/
public void moveToFront(E e) {
if (e != first) {
unlink(e);
linkFirst(e);
}
}
/**
* Moves the element to the back of the deque so that it becomes the last
* element.
*
* @param e the linked element
*/
public void moveToBack(E e) {
if (e != last) {
unlink(e);
linkLast(e);
}
}
@Override
public E peek() {
return peekFirst();
}
@Override
public E peekFirst() {
return first;
}
@Override
public E peekLast() {
return last;
}
@Override
public E getFirst() {
checkNotEmpty();
return peekFirst();
}
@Override
public E getLast() {
checkNotEmpty();
return peekLast();
}
@Override
public E element() {
return getFirst();
}
@Override
public boolean offer(E e) {
return offerLast(e);
}
@Override
public boolean offerFirst(E e) {
if (contains(e)) {
return false;
}
linkFirst(e);
return true;
}
@Override
public boolean offerLast(E e) {
if (contains(e)) {
return false;
}
linkLast(e);
return true;
}
@Override
public boolean add(E e) {
return offerLast(e);
}
@Override
public void addFirst(E e) {
if (!offerFirst(e)) {
throw new IllegalArgumentException();
}
}
@Override
public void addLast(E e) {
if (!offerLast(e)) {
throw new IllegalArgumentException();
}
}
@Override
public E poll() {
return pollFirst();
}
@Override
public E pollFirst() {
return isEmpty() ? null : unlinkFirst();
}
@Override
public E pollLast() {
return isEmpty() ? null : unlinkLast();
}
@Override
public E remove() {
return removeFirst();
}
@Override
@SuppressWarnings("unchecked")
public boolean remove(Object o) {
return (o instanceof Linked<?>) && remove((E) o);
}
// A fast-path removal
boolean remove(E e) {
if (contains(e)) {
unlink(e);
return true;
}
return false;
}
@Override
public E removeFirst() {
checkNotEmpty();
return pollFirst();
}
@Override
public boolean removeFirstOccurrence(Object o) {
return remove(o);
}
@Override
public E removeLast() {
checkNotEmpty();
return pollLast();
}
@Override
public boolean removeLastOccurrence(Object o) {
return remove(o);
}
@Override
public boolean removeAll(Collection<?> c) {
boolean modified = false;
for (Object o : c) {
modified |= remove(o);
}
return modified;
}
@Override
public void push(E e) {
addFirst(e);
}
@Override
public E pop() {
return removeFirst();
}
@Override
public Iterator<E> iterator() {
return new AbstractLinkedIterator(first) {
@Override E computeNext() {
return cursor.getNext();
}
};
}
@Override
public Iterator<E> descendingIterator() {
return new AbstractLinkedIterator(last) {
@Override E computeNext() {
return cursor.getPrevious();
}
};
}
abstract class AbstractLinkedIterator implements Iterator<E> {
E cursor;
/**
* Creates an iterator that can can traverse the deque.
*
* @param start the initial element to begin traversal from
*/
AbstractLinkedIterator(E start) {
cursor = start;
}
@Override
public boolean hasNext() {
return (cursor != null);
}
@Override
public E next() {
if (!hasNext()) {
throw new NoSuchElementException();
}
E e = cursor;
cursor = computeNext();
return e;
}
@Override
public void remove() {
throw new UnsupportedOperationException();
}
/**
* Retrieves the next element to traverse to or <tt>null</tt> if there are
* no more elements.
*/
abstract E computeNext();
}
}
/**
* An element that is linked on the {@link Deque}.
*/
interface Linked<T extends Linked<T>> {
/**
* Retrieves the previous element or <tt>null</tt> if either the element is
* unlinked or the first element on the deque.
*/
T getPrevious();
/** Sets the previous element or <tt>null</tt> if there is no link. */
void setPrevious(T prev);
/**
* Retrieves the next element or <tt>null</tt> if either the element is
* unlinked or the last element on the deque.
*/
T getNext();
/** Sets the next element or <tt>null</tt> if there is no link. */
void setNext(T next);
}

View file

@ -0,0 +1,36 @@
/*
* Copyright 2010 Google Inc. All Rights Reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.googlecode.concurrentlinkedhashmap;
/**
* A class that can determine the weight of a value. The total weight threshold
* is used to determine when an eviction is required.
*
* @author ben.manes@gmail.com (Ben Manes)
* @see <a href="http://code.google.com/p/concurrentlinkedhashmap/">
* http://code.google.com/p/concurrentlinkedhashmap/</a>
*/
public interface Weigher<V> {
/**
* Measures an object's weight to determine how many units of capacity that
* the value consumes. A value must consume a minimum of one unit.
*
* @param value the object to weigh
* @return the object's weight
*/
int weightOf(V value);
}

View file

@ -0,0 +1,282 @@
/*
* Copyright 2010 Google Inc. All Rights Reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.googlecode.concurrentlinkedhashmap;
import static com.googlecode.concurrentlinkedhashmap.ConcurrentLinkedHashMap.checkNotNull;
import java.io.Serializable;
import java.util.Collection;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;
/**
* A common set of {@link Weigher} and {@link EntryWeigher} implementations.
*
* @author ben.manes@gmail.com (Ben Manes)
* @see <a href="http://code.google.com/p/concurrentlinkedhashmap/">
* http://code.google.com/p/concurrentlinkedhashmap/</a>
*/
public final class Weighers {
private Weighers() {
throw new AssertionError();
}
/**
* A entry weigher backed by the specified weigher. The weight of the value
* determines the weight of the entry.
*
* @param weigher the weigher to be "wrapped" in a entry weigher.
* @return A entry weigher view of the specified weigher.
*/
public static <K, V> EntryWeigher<K, V> asEntryWeigher(
final Weigher<? super V> weigher) {
return (weigher == singleton())
? Weighers.<K, V>entrySingleton()
: new EntryWeigherView<K, V>(weigher);
}
/**
* A weigher where an entry has a weight of <tt>1</tt>. A map bounded with
* this weigher will evict when the number of key-value pairs exceeds the
* capacity.
*
* @return A weigher where a value takes one unit of capacity.
*/
@SuppressWarnings({"cast", "unchecked"})
public static <K, V> EntryWeigher<K, V> entrySingleton() {
return (EntryWeigher<K, V>) SingletonEntryWeigher.INSTANCE;
}
/**
* A weigher where a value has a weight of <tt>1</tt>. A map bounded with
* this weigher will evict when the number of key-value pairs exceeds the
* capacity.
*
* @return A weigher where a value takes one unit of capacity.
*/
@SuppressWarnings({"cast", "unchecked"})
public static <V> Weigher<V> singleton() {
return (Weigher<V>) SingletonWeigher.INSTANCE;
}
/**
* A weigher where the value is a byte array and its weight is the number of
* bytes. A map bounded with this weigher will evict when the number of bytes
* exceeds the capacity rather than the number of key-value pairs in the map.
* This allows for restricting the capacity based on the memory-consumption
* and is primarily for usage by dedicated caching servers that hold the
* serialized data.
* <p>
* A value with a weight of <tt>0</tt> will be rejected by the map. If a value
* with this weight can occur then the caller should eagerly evaluate the
* value and treat it as a removal operation. Alternatively, a custom weigher
* may be specified on the map to assign an empty value a positive weight.
*
* @return A weigher where each byte takes one unit of capacity.
*/
public static Weigher<byte[]> byteArray() {
return ByteArrayWeigher.INSTANCE;
}
/**
* A weigher where the value is a {@link Iterable} and its weight is the
* number of elements. This weigher only should be used when the alternative
* {@link #collection()} weigher cannot be, as evaluation takes O(n) time. A
* map bounded with this weigher will evict when the total number of elements
* exceeds the capacity rather than the number of key-value pairs in the map.
* <p>
* A value with a weight of <tt>0</tt> will be rejected by the map. If a value
* with this weight can occur then the caller should eagerly evaluate the
* value and treat it as a removal operation. Alternatively, a custom weigher
* may be specified on the map to assign an empty value a positive weight.
*
* @return A weigher where each element takes one unit of capacity.
*/
@SuppressWarnings({"cast", "unchecked"})
public static <E> Weigher<? super Iterable<E>> iterable() {
return (Weigher<Iterable<E>>) (Weigher<?>) IterableWeigher.INSTANCE;
}
/**
* A weigher where the value is a {@link Collection} and its weight is the
* number of elements. A map bounded with this weigher will evict when the
* total number of elements exceeds the capacity rather than the number of
* key-value pairs in the map.
* <p>
* A value with a weight of <tt>0</tt> will be rejected by the map. If a value
* with this weight can occur then the caller should eagerly evaluate the
* value and treat it as a removal operation. Alternatively, a custom weigher
* may be specified on the map to assign an empty value a positive weight.
*
* @return A weigher where each element takes one unit of capacity.
*/
@SuppressWarnings({"cast", "unchecked"})
public static <E> Weigher<? super Collection<E>> collection() {
return (Weigher<Collection<E>>) (Weigher<?>) CollectionWeigher.INSTANCE;
}
/**
* A weigher where the value is a {@link List} and its weight is the number
* of elements. A map bounded with this weigher will evict when the total
* number of elements exceeds the capacity rather than the number of
* key-value pairs in the map.
* <p>
* A value with a weight of <tt>0</tt> will be rejected by the map. If a value
* with this weight can occur then the caller should eagerly evaluate the
* value and treat it as a removal operation. Alternatively, a custom weigher
* may be specified on the map to assign an empty value a positive weight.
*
* @return A weigher where each element takes one unit of capacity.
*/
@SuppressWarnings({"cast", "unchecked"})
public static <E> Weigher<? super List<E>> list() {
return (Weigher<List<E>>) (Weigher<?>) ListWeigher.INSTANCE;
}
/**
* A weigher where the value is a {@link Set} and its weight is the number
* of elements. A map bounded with this weigher will evict when the total
* number of elements exceeds the capacity rather than the number of
* key-value pairs in the map.
* <p>
* A value with a weight of <tt>0</tt> will be rejected by the map. If a value
* with this weight can occur then the caller should eagerly evaluate the
* value and treat it as a removal operation. Alternatively, a custom weigher
* may be specified on the map to assign an empty value a positive weight.
*
* @return A weigher where each element takes one unit of capacity.
*/
@SuppressWarnings({"cast", "unchecked"})
public static <E> Weigher<? super Set<E>> set() {
return (Weigher<Set<E>>) (Weigher<?>) SetWeigher.INSTANCE;
}
/**
* A weigher where the value is a {@link Map} and its weight is the number of
* entries. A map bounded with this weigher will evict when the total number of
* entries across all values exceeds the capacity rather than the number of
* key-value pairs in the map.
* <p>
* A value with a weight of <tt>0</tt> will be rejected by the map. If a value
* with this weight can occur then the caller should eagerly evaluate the
* value and treat it as a removal operation. Alternatively, a custom weigher
* may be specified on the map to assign an empty value a positive weight.
*
* @return A weigher where each entry takes one unit of capacity.
*/
@SuppressWarnings({"cast", "unchecked"})
public static <A, B> Weigher<? super Map<A, B>> map() {
return (Weigher<Map<A, B>>) (Weigher<?>) MapWeigher.INSTANCE;
}
static final class EntryWeigherView<K, V> implements EntryWeigher<K, V>, Serializable {
static final long serialVersionUID = 1;
final Weigher<? super V> weigher;
EntryWeigherView(Weigher<? super V> weigher) {
checkNotNull(weigher);
this.weigher = weigher;
}
@Override
public int weightOf(K key, V value) {
return weigher.weightOf(value);
}
}
enum SingletonEntryWeigher implements EntryWeigher<Object, Object> {
INSTANCE;
@Override
public int weightOf(Object key, Object value) {
return 1;
}
}
enum SingletonWeigher implements Weigher<Object> {
INSTANCE;
@Override
public int weightOf(Object value) {
return 1;
}
}
enum ByteArrayWeigher implements Weigher<byte[]> {
INSTANCE;
@Override
public int weightOf(byte[] value) {
return value.length;
}
}
enum IterableWeigher implements Weigher<Iterable<?>> {
INSTANCE;
@Override
public int weightOf(Iterable<?> values) {
if (values instanceof Collection<?>) {
return ((Collection<?>) values).size();
}
int size = 0;
for (Iterator<?> i = values.iterator(); i.hasNext();) {
i.next();
size++;
}
return size;
}
}
enum CollectionWeigher implements Weigher<Collection<?>> {
INSTANCE;
@Override
public int weightOf(Collection<?> values) {
return values.size();
}
}
enum ListWeigher implements Weigher<List<?>> {
INSTANCE;
@Override
public int weightOf(List<?> values) {
return values.size();
}
}
enum SetWeigher implements Weigher<Set<?>> {
INSTANCE;
@Override
public int weightOf(Set<?> values) {
return values.size();
}
}
enum MapWeigher implements Weigher<Map<?, ?>> {
INSTANCE;
@Override
public int weightOf(Map<?, ?> values) {
return values.size();
}
}
}

View file

@ -0,0 +1,41 @@
/*
* Copyright 2011 Google Inc. All Rights Reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
/**
* This package contains an implementation of a bounded
* {@link java.util.concurrent.ConcurrentMap} data structure.
* <p>
* {@link com.googlecode.concurrentlinkedhashmap.Weigher} is a simple interface
* for determining how many units of capacity an entry consumes. Depending on
* which concrete Weigher class is used, an entry may consume a different amount
* of space within the cache. The
* {@link com.googlecode.concurrentlinkedhashmap.Weighers} class provides
* utility methods for obtaining the most common kinds of implementations.
* <p>
* {@link com.googlecode.concurrentlinkedhashmap.EvictionListener} provides the
* ability to be notified when an entry is evicted from the map. An eviction
* occurs when the entry was automatically removed due to the map exceeding a
* capacity threshold. It is not called when an entry was explicitly removed.
* <p>
* The {@link com.googlecode.concurrentlinkedhashmap.ConcurrentLinkedHashMap}
* class supplies an efficient, scalable, thread-safe, bounded map. As with the
* <tt>Java Collections Framework</tt> the "Concurrent" prefix is used to
* indicate that the map is not governed by a single exclusion lock.
*
* @see <a href="http://code.google.com/p/concurrentlinkedhashmap/">
* http://code.google.com/p/concurrentlinkedhashmap/</a>
*/
package com.googlecode.concurrentlinkedhashmap;

View file

@ -68,6 +68,7 @@
style="?android:attr/progressBarStyleHorizontal"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
tools:visibility="visible"
android:visibility="gone"/>
</LinearLayout>

View file

@ -2011,4 +2011,5 @@ Afghanistan, Albania, Algeria, Andorra, Angola, Anguilla, Antigua and Barbuda, A
<string name="activate_srtm_plugin">Please activate SRTM plugin</string>
<string name="later">Later</string>
<string name="get_full_version">Get full version</string>
<string name="downloads">Downloads</string>
</resources>

View file

@ -35,6 +35,8 @@ import android.widget.ArrayAdapter;
import android.widget.ImageView;
import android.widget.Toast;
import com.googlecode.concurrentlinkedhashmap.ConcurrentLinkedHashMap;
import net.osmand.AndroidUtils;
import net.osmand.IProgress;
import net.osmand.IndexConstants;
@ -77,7 +79,6 @@ import java.util.Arrays;
import java.util.Collection;
import java.util.Comparator;
import java.util.Iterator;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
@ -129,18 +130,22 @@ public class AudioVideoNotesPlugin extends OsmandPlugin {
public final OsmandPreference<Boolean> SHOW_RECORDINGS;
private DataTileManager<Recording> recordings = new DataTileManager<AudioVideoNotesPlugin.Recording>(14);
private Map<String, Recording> recordingByFileName = new LinkedHashMap<String, Recording>();
private Map<String, Recording> recordingByFileName =
new ConcurrentLinkedHashMap.Builder<String, Recording>()
.maximumWeightedCapacity(1000)
.build();
private AudioNotesLayer audioNotesLayer;
private MapActivity activity;
private MediaRecorder mediaRec;
private File lastTakingPhoto;
private final static char SPLIT_DESC = ' ';
private final static char SPLIT_DESC = ' ';
public static class Recording {
public Recording(File f) {
this.file = f;
}
private File file;
private double lat;
@ -177,7 +182,7 @@ public class AudioVideoNotesPlugin extends OsmandPlugin {
public File getFile() {
return file;
}
public boolean setName(String name) {
File directory = file.getParentFile();
@ -193,24 +198,24 @@ public class AudioVideoNotesPlugin extends OsmandPlugin {
public String getFileName() {
return file.getName();
}
public String getDescriptionName(String fileName) {
int hashInd = fileName.lastIndexOf(SPLIT_DESC);
//backward compatibility
if( fileName.indexOf('.') - fileName.indexOf('_') > 12 &&
if (fileName.indexOf('.') - fileName.indexOf('_') > 12 &&
hashInd < fileName.indexOf('_')) {
hashInd = fileName.indexOf('_');
}
if(hashInd == -1) {
if (hashInd == -1) {
return null;
} else {
return fileName.substring(0, hashInd);
}
}
public String getOtherName(String fileName) {
String descriptionName = getDescriptionName(fileName);
if(descriptionName != null) {
if (descriptionName != null) {
return fileName.substring(descriptionName.length() + 1); // SPLIT_DESC
} else {
return fileName;
@ -232,8 +237,8 @@ public class AudioVideoNotesPlugin extends OsmandPlugin {
return "";
}
public String getSearchHistoryType(){
if (isPhoto()){
public String getSearchHistoryType() {
if (isPhoto()) {
return PointDescription.POINT_TYPE_PHOTO_NOTE;
} else if (isVideo()) {
return PointDescription.POINT_TYPE_VIDEO_NOTE;
@ -349,7 +354,7 @@ public class AudioVideoNotesPlugin extends OsmandPlugin {
return ctx.getString(R.string.recording_description, "", getDuration(ctx), time)
.trim();
}
public String getSmallDescription(Context ctx) {
String time = AndroidUtils.formatDateTime(ctx, file.lastModified());
if (isPhoto()) {
@ -357,7 +362,7 @@ public class AudioVideoNotesPlugin extends OsmandPlugin {
}
updateInternalDescription();
return time + " " + getDuration(ctx);
}
private String getDuration(Context ctx) {
@ -444,7 +449,7 @@ public class AudioVideoNotesPlugin extends OsmandPlugin {
}
audioNotesLayer = new AudioNotesLayer(activity, this);
activity.getMapView().addLayer(audioNotesLayer, 3.5f);
if(recordControl == null) {
if (recordControl == null) {
registerWidget(activity);
}
}
@ -534,7 +539,7 @@ public class AudioVideoNotesPlugin extends OsmandPlugin {
} else if (audioNotesLayer != null) {
mapView.removeLayer(audioNotesLayer);
}
if(recordControl == null) {
if (recordControl == null) {
registerWidget(activity);
}
} else {
@ -543,7 +548,7 @@ public class AudioVideoNotesPlugin extends OsmandPlugin {
audioNotesLayer = null;
}
MapInfoLayer mapInfoLayer = activity.getMapLayers().getMapInfoLayer();
if(recordControl != null && mapInfoLayer != null) {
if (recordControl != null && mapInfoLayer != null) {
mapInfoLayer.removeSideWidget(recordControl);
recordControl = null;
mapInfoLayer.recreateControls();
@ -1290,7 +1295,7 @@ public class AudioVideoNotesPlugin extends OsmandPlugin {
}
}
}
@Override
public int getLogoResourceId() {
return R.drawable.ic_action_micro_dark;

View file

@ -7,6 +7,7 @@ import android.content.ActivityNotFoundException;
import android.content.Context;
import android.content.DialogInterface;
import android.content.Intent;
import android.graphics.drawable.Drawable;
import android.net.Uri;
import android.os.AsyncTask;
import android.os.Bundle;
@ -14,16 +15,18 @@ import android.support.annotation.NonNull;
import android.support.v4.app.DialogFragment;
import android.support.v4.app.Fragment;
import android.support.v4.app.FragmentActivity;
import android.support.v4.app.FragmentTransaction;
import android.support.v4.app.ListFragment;
import android.support.v4.view.ViewPager;
import android.view.LayoutInflater;
import android.view.MenuItem;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ArrayAdapter;
import android.widget.BaseAdapter;
import android.widget.BaseExpandableListAdapter;
import android.widget.Button;
import android.widget.ExpandableListAdapter;
import android.widget.ImageView;
import android.widget.ListAdapter;
import android.widget.ProgressBar;
import android.widget.TextView;
@ -109,8 +112,10 @@ public class DownloadActivity extends BaseDownloadActivity implements RegionDial
ViewPager viewPager = (ViewPager) findViewById(R.id.pager);
PagerSlidingTabStrip mSlidingTabLayout = (PagerSlidingTabStrip) findViewById(R.id.sliding_tabs);
mTabs.add(new TabActivity.TabItem(R.string.download_tab_local,
getString(R.string.download_tab_local), LocalIndexesFragment.class));
mTabs.add(new TabActivity.TabItem(R.string.download_tab_downloads,
getString(R.string.download_tab_downloads), WorldItemsFragment.class));
// mTabs.add(new TabActivity.TabItem(R.string.download_tab_local,
// getString(R.string.download_tab_local), LocalIndexesFragment.class));
mTabs.add(new TabActivity.TabItem(R.string.download_tab_downloads,
getString(R.string.download_tab_downloads), DownloadIndexFragment.class));
mTabs.add(new TabActivity.TabItem(R.string.download_tab_updates,
@ -118,8 +123,6 @@ public class DownloadActivity extends BaseDownloadActivity implements RegionDial
// mTabs.add(new TabActivity.TabItem(R.string.download_tab_local,
// getString(R.string.download_tab_local), NewLocalIndexesFragment.class));
mTabs.add(new TabActivity.TabItem(R.string.download_tab_downloads,
getString(R.string.download_tab_downloads), WorldItemsFragment.class));
viewPager.setAdapter(new TabActivity.OsmandFragmentPagerAdapter(getSupportFragmentManager(), mTabs));
mSlidingTabLayout.setViewPager(viewPager);
@ -200,7 +203,7 @@ public class DownloadActivity extends BaseDownloadActivity implements RegionDial
protected void onResume() {
super.onResume();
getMyApplication().getAppCustomization().resumeActivity(DownloadActivity.class, this);
initFreeVersionBanner(findViewById(R.id.mainLayout));
registerFreeVersionBanner(findViewById(R.id.mainLayout));
}
@ -571,19 +574,18 @@ public class DownloadActivity extends BaseDownloadActivity implements RegionDial
}
public void initFreeVersionBanner(View view) {
public void registerFreeVersionBanner(View view) {
visibleBanner = new BannerAndDownloadFreeVersion(view, this);
updateProgress(true);
}
public void showDialog(FragmentActivity activity, DialogFragment fragment) {
fragment.show(activity.getSupportFragmentManager(), "dialog");
}
@Override
public void onDialogDismissed() {
initFreeVersionBanner(findViewById(R.id.mainLayout));
registerFreeVersionBanner(findViewById(R.id.mainLayout));
}
private static class ToggleCollapseFreeVersionBanner implements View.OnClickListener {
@ -623,12 +625,12 @@ public class DownloadActivity extends BaseDownloadActivity implements RegionDial
private final TextView downloadsLeftTextView;
private final View laterButton;
private final Context ctx;
private final FragmentActivity ctx;
private final OsmandApplication application;
private final boolean shouldShowFreeVersionBanner;
private final View freeVersionBannerTitle;
public BannerAndDownloadFreeVersion(View view, Context ctx) {
public BannerAndDownloadFreeVersion(View view, final FragmentActivity ctx) {
this.ctx = ctx;
application = (OsmandApplication) ctx.getApplicationContext();
freeVersionBanner = view.findViewById(R.id.freeVersionBanner);
@ -649,6 +651,12 @@ public class DownloadActivity extends BaseDownloadActivity implements RegionDial
initFreeVersionBanner();
updateFreeVersionBanner();
downloadProgressLayout.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
new ActiveDownloadsDialogFragment().show(ctx.getSupportFragmentManager(), "dialog");
}
});
}
public void updateProgress(int countedDownloads,
@ -742,4 +750,84 @@ public class DownloadActivity extends BaseDownloadActivity implements RegionDial
}
}
}
public static class ActiveDownloadsDialogFragment extends DialogFragment {
@NonNull
@Override
public Dialog onCreateDialog(Bundle savedInstanceState) {
AlertDialog.Builder builder = new Builder(getActivity());
builder.setTitle(R.string.downloads).setNegativeButton(R.string.shared_string_cancel, null);
Collection<List<DownloadEntry>> vs =
DownloadActivity.downloadListIndexThread.getEntriesToDownload().values();
ArrayList<DownloadEntry> downloadEntries = new ArrayList<>();
for (List<DownloadEntry> list : vs) {
downloadEntries.addAll(list);
}
builder.setAdapter(new DownloadEntryAdapter(getActivity(), downloadEntries), null);
return builder.create();
}
private static class DownloadEntryAdapter extends ArrayAdapter<DownloadEntry> {
private final Drawable deleteDrawable;
public DownloadEntryAdapter(Context context, List<DownloadEntry> objects) {
super(context, R.layout.two_line_with_images_list_item, objects);
deleteDrawable = ((OsmandApplication) context.getApplicationContext()).getIconsCache()
.getPaintedContentIcon(R.drawable.ic_action_remove_dark,
context.getResources().getColor(R.color.dash_search_icon_dark));
}
@Override
public View getView(int position, View convertView, ViewGroup parent) {
if (convertView == null) {
convertView = LayoutInflater.from(parent.getContext())
.inflate(R.layout.two_line_with_images_list_item, parent, false);
DownloadEntryViewHolder viewHolder =
new DownloadEntryViewHolder(convertView, deleteDrawable);
convertView.setTag(viewHolder);
}
DownloadEntryViewHolder viewHolder = (DownloadEntryViewHolder) convertView.getTag();
viewHolder.bindDownloadEntry(getItem(position));
return convertView;
}
}
private static class DownloadEntryViewHolder {
private final TextView nameTextView;
private final TextView descrTextView;
private final ImageView leftImageView;
private final ImageView rightImageButton;
private final Button rightButton;
private final ProgressBar progressBar;
private final TextView mapDateTextView;
private final Drawable deleteDrawable;
private DownloadEntryViewHolder(View convertView, Drawable deleteDrawable) {
this.deleteDrawable = deleteDrawable;
nameTextView = (TextView) convertView.findViewById(R.id.name);
descrTextView = (TextView) convertView.findViewById(R.id.description);
leftImageView = (ImageView) convertView.findViewById(R.id.leftImageView);
rightImageButton = (ImageView) convertView.findViewById(R.id.rightImageButton);
rightButton = (Button) convertView.findViewById(R.id.rightButton);
progressBar = (ProgressBar) convertView.findViewById(R.id.progressBar);
mapDateTextView = (TextView) convertView.findViewById(R.id.mapDateTextView);
}
public void bindDownloadEntry(DownloadEntry downloadEntry) {
nameTextView.setText(downloadEntry.baseName);
descrTextView.setText(String.format("%1$s MBb from %2$s Mb", 123.440,
downloadEntry.sizeMB));
rightImageButton.setImageDrawable(deleteDrawable);
rightImageButton.setVisibility(View.VISIBLE);
rightImageButton.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
}
});
progressBar.setVisibility(View.VISIBLE);
progressBar.setIndeterminate(true);
}
}
}
}

View file

@ -32,6 +32,4 @@ public class DownloadEntry {
this.assetName = assetName;
isAsset = true;
}
}

View file

@ -1,7 +1,5 @@
package net.osmand.plus.download;
import android.annotation.SuppressLint;
import android.app.AlertDialog;
import android.content.ActivityNotFoundException;
@ -30,7 +28,6 @@ import net.osmand.plus.WorldRegion;
import net.osmand.plus.base.BasicProgressAsyncTask;
import net.osmand.plus.download.DownloadFileHelper.DownloadFileShowWarning;
import net.osmand.plus.download.DownloadOsmandIndexesHelper.AssetIndexItem;
import net.osmand.plus.download.items.ItemsListBuilder;
import net.osmand.plus.helpers.DatabaseHelper;
import net.osmand.plus.resources.ResourceManager;
import net.osmand.util.Algorithms;
@ -304,7 +301,10 @@ public class DownloadIndexesThread {
} else if (o instanceof String) {
String message = (String) o;
if (!message.equals("I/O error occurred : Interrupted")) {
AccessibleToast.makeText(ctx, message, Toast.LENGTH_LONG).show();
if (uiActivity == null ||
!message.equals(uiActivity.getString(R.string.shared_string_download_successful))) {
AccessibleToast.makeText(ctx, message, Toast.LENGTH_LONG).show();
}
}
}
}
@ -472,7 +472,6 @@ public class DownloadIndexesThread {
@Override
public void showWarning(String warning) {
publishProgress(warning);
}
public boolean downloadFile(DownloadEntry de, List<File> filesToReindex, boolean forceWifi)

View file

@ -70,7 +70,6 @@ public class ItemViewHolder {
rightButton = (Button) convertView.findViewById(R.id.rightButton);
progressBar = (ProgressBar) convertView.findViewById(R.id.progressBar);
mapDateTextView = (TextView) convertView.findViewById(R.id.mapDateTextView);
;
TypedValue typedValue = new TypedValue();
Resources.Theme theme = convertView.getContext().getTheme();
@ -108,11 +107,6 @@ public class ItemViewHolder {
}
if ((indexItem.getType() == DownloadActivityType.SRTM_COUNTRY_FILE ||
indexItem.getType() == DownloadActivityType.HILLSHADE_FILE) && srtmDisabled) {
if (indexItem.getType() == DownloadActivityType.SRTM_COUNTRY_FILE) {
nameTextView.setText(context.getString(R.string.srtm_plugin_disabled));
} else {
nameTextView.setText(context.getString(R.string.hillshade_layer_disabled));
}
OsmandPlugin srtmPlugin = OsmandPlugin.getPlugin(SRTMPlugin.class);
if (srtmPlugin == null || srtmPlugin.needsInstallation()) {
rightButtonAction = RightButtonAction.ASK_FOR_SRTM_PLUGIN_PURCHASE;
@ -124,7 +118,8 @@ public class ItemViewHolder {
} else if (indexItem.getType() == DownloadActivityType.WIKIPEDIA_FILE && freeVersion) {
rightButtonAction = RightButtonAction.ASK_FOR_FULL_VERSION_PURCHASE;
disabled = true;
} else if (showTypeInTitle) {
}
if (showTypeInTitle) {
nameTextView.setText(indexItem.getType().getString(context));
} else {
nameTextView.setText(indexItem.getVisibleName(context, context.getMyApplication().getRegions()));
@ -196,9 +191,8 @@ public class ItemViewHolder {
if (indexFileNames != null && indexItem.isAlreadyDownloaded(indexFileNames)) {
boolean outdated = false;
String date = null;
String date;
if (indexItem.getType() == DownloadActivityType.HILLSHADE_FILE) {
// TODO write logic for outdated
date = indexItem.getDate(dateFormat);
} else {
String sfName = indexItem.getTargetFileName();
@ -212,7 +206,6 @@ public class ItemViewHolder {
int colorId = outdated ? R.color.color_distance : R.color.color_ok;
mapDateTextView.setTextColor(context.getResources().getColor(colorId));
}
}
public void bindRegion(WorldRegion region, DownloadActivity context) {
@ -227,6 +220,8 @@ public class ItemViewHolder {
}
}
descrTextView.setVisibility(View.GONE);
mapDateTextView.setVisibility(View.GONE);
leftImageView.setImageDrawable(getContextIcon(context, R.drawable.ic_map));
rightImageButton.setVisibility(View.GONE);
progressBar.setVisibility(View.GONE);

View file

@ -65,11 +65,11 @@ public class RegionDialogFragment extends DialogFragment{
toolbar.setTitle(region.getName());
}
}
getDownloadActivity().initFreeVersionBanner(view);
getDownloadActivity().registerFreeVersionBanner(view);
listener = new DialogDismissListener() {
@Override
public void onDialogDismissed() {
getDownloadActivity().initFreeVersionBanner(view);
getDownloadActivity().registerFreeVersionBanner(view);
}
};
return view;

View file

@ -101,7 +101,7 @@ public class SearchDialogFragment extends DialogFragment {
SearchItemsFragment.createInstance(searchText), SearchItemsFragment.TAG).commit();
}
getDownloadActivity().initFreeVersionBanner(view);
getDownloadActivity().registerFreeVersionBanner(view);
return view;
}

View file

@ -74,7 +74,7 @@ public class VoiceDialogFragment extends DialogFragment {
ItemsListBuilder builder = getDownloadActivity().getItemsBuilder();
toolbar.setTitle(builder.getVoicePromtName(voicePromptsType));
}
((DownloadActivity)getActivity()).initFreeVersionBanner(view);
((DownloadActivity)getActivity()).registerFreeVersionBanner(view);
return view;
}

View file

@ -14,7 +14,9 @@ import net.osmand.plus.Version;
import net.osmand.plus.WorldRegion;
import net.osmand.plus.activities.OsmandBaseExpandableListAdapter;
import net.osmand.plus.activities.OsmandExpandableListFragment;
import net.osmand.plus.download.BaseDownloadActivity;
import net.osmand.plus.download.DownloadActivity;
import net.osmand.plus.download.IndexItem;
import net.osmand.plus.download.items.ItemsListBuilder.VoicePromptsType;
import net.osmand.plus.openseamapsplugin.NauticalMapsPlugin;
import net.osmand.plus.srtmplugin.SRTMPlugin;
@ -141,6 +143,15 @@ public class WorldItemsFragment extends OsmandExpandableListFragment {
getDownloadActivity().showDialog(getActivity(),
VoiceDialogFragment.createInstance(VoicePromptsType.TTS));
}
}else if (groupPosition == worldMapsIndex) {
if(((ItemViewHolder) v.getTag()).isItemAvailable()) {
IndexItem indexItem = ((ItemsListBuilder.ResourceItem)
listAdapter.getChild(groupPosition, childPosition)).getIndexItem();
((BaseDownloadActivity) getActivity())
.startDownload(indexItem);
return true;
}
}
return false;
}