15cd681c345db8f606d7d5a8662e20e059f21a86cGeorge Mount/*
25cd681c345db8f606d7d5a8662e20e059f21a86cGeorge Mount * Copyright (C) 2015 The Android Open Source Project
35cd681c345db8f606d7d5a8662e20e059f21a86cGeorge Mount *
45cd681c345db8f606d7d5a8662e20e059f21a86cGeorge Mount * Licensed under the Apache License, Version 2.0 (the "License");
55cd681c345db8f606d7d5a8662e20e059f21a86cGeorge Mount * you may not use this file except in compliance with the License.
65cd681c345db8f606d7d5a8662e20e059f21a86cGeorge Mount * You may obtain a copy of the License at
75cd681c345db8f606d7d5a8662e20e059f21a86cGeorge Mount *
85cd681c345db8f606d7d5a8662e20e059f21a86cGeorge Mount *      http://www.apache.org/licenses/LICENSE-2.0
95cd681c345db8f606d7d5a8662e20e059f21a86cGeorge Mount *
105cd681c345db8f606d7d5a8662e20e059f21a86cGeorge Mount * Unless required by applicable law or agreed to in writing, software
115cd681c345db8f606d7d5a8662e20e059f21a86cGeorge Mount * distributed under the License is distributed on an "AS IS" BASIS,
125cd681c345db8f606d7d5a8662e20e059f21a86cGeorge Mount * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
135cd681c345db8f606d7d5a8662e20e059f21a86cGeorge Mount * See the License for the specific language governing permissions and
145cd681c345db8f606d7d5a8662e20e059f21a86cGeorge Mount * limitations under the License.
155cd681c345db8f606d7d5a8662e20e059f21a86cGeorge Mount */
16fead9ca09b117136b35bc5bf137340a754f9edddGeorge Mountpackage android.databinding;
175cd681c345db8f606d7d5a8662e20e059f21a86cGeorge Mount
185cd681c345db8f606d7d5a8662e20e059f21a86cGeorge Mountimport android.support.v4.util.Pools;
195cd681c345db8f606d7d5a8662e20e059f21a86cGeorge Mount
20c9a5d6f140f732ca0ff279a4b1ee315072e1c422George Mount/**
21c9a5d6f140f732ca0ff279a4b1ee315072e1c422George Mount * Utility class for managing ObservableList callbacks.
22c9a5d6f140f732ca0ff279a4b1ee315072e1c422George Mount */
235cd681c345db8f606d7d5a8662e20e059f21a86cGeorge Mountpublic class ListChangeRegistry
242c86cdbaf189e2b1774af7f64a2974de9321673fGeorge Mount        extends
25722fe711207a37783dfa7142284b0ebe5bd503fbGeorge Mount        CallbackRegistry<ObservableList.OnListChangedCallback, ObservableList,
26722fe711207a37783dfa7142284b0ebe5bd503fbGeorge Mount                ListChangeRegistry.ListChanges> {
275cd681c345db8f606d7d5a8662e20e059f21a86cGeorge Mount    private static final Pools.SynchronizedPool<ListChanges> sListChanges =
289784c9aaedeb863018f5fcaa0a598e8e2f8ed2f3Yigit Boyar            new Pools.SynchronizedPool<ListChanges>(10);
295cd681c345db8f606d7d5a8662e20e059f21a86cGeorge Mount
305cd681c345db8f606d7d5a8662e20e059f21a86cGeorge Mount    private static final int ALL = 0;
315cd681c345db8f606d7d5a8662e20e059f21a86cGeorge Mount    private static final int CHANGED = 1;
325cd681c345db8f606d7d5a8662e20e059f21a86cGeorge Mount    private static final int INSERTED = 2;
335cd681c345db8f606d7d5a8662e20e059f21a86cGeorge Mount    private static final int MOVED = 3;
345cd681c345db8f606d7d5a8662e20e059f21a86cGeorge Mount    private static final int REMOVED = 4;
355cd681c345db8f606d7d5a8662e20e059f21a86cGeorge Mount
36722fe711207a37783dfa7142284b0ebe5bd503fbGeorge Mount    private static final CallbackRegistry.NotifierCallback<ObservableList.OnListChangedCallback,
37722fe711207a37783dfa7142284b0ebe5bd503fbGeorge Mount            ObservableList, ListChanges> NOTIFIER_CALLBACK = new CallbackRegistry.NotifierCallback<
38722fe711207a37783dfa7142284b0ebe5bd503fbGeorge Mount            ObservableList.OnListChangedCallback, ObservableList, ListChanges>() {
395cd681c345db8f606d7d5a8662e20e059f21a86cGeorge Mount        @Override
40722fe711207a37783dfa7142284b0ebe5bd503fbGeorge Mount        public void onNotifyCallback(ObservableList.OnListChangedCallback callback,
41722fe711207a37783dfa7142284b0ebe5bd503fbGeorge Mount                ObservableList sender, int notificationType, ListChanges listChanges) {
425cd681c345db8f606d7d5a8662e20e059f21a86cGeorge Mount            switch (notificationType) {
435cd681c345db8f606d7d5a8662e20e059f21a86cGeorge Mount                case CHANGED:
44722fe711207a37783dfa7142284b0ebe5bd503fbGeorge Mount                    callback.onItemRangeChanged(sender, listChanges.start, listChanges.count);
455cd681c345db8f606d7d5a8662e20e059f21a86cGeorge Mount                    break;
465cd681c345db8f606d7d5a8662e20e059f21a86cGeorge Mount                case INSERTED:
47722fe711207a37783dfa7142284b0ebe5bd503fbGeorge Mount                    callback.onItemRangeInserted(sender, listChanges.start, listChanges.count);
485cd681c345db8f606d7d5a8662e20e059f21a86cGeorge Mount                    break;
495cd681c345db8f606d7d5a8662e20e059f21a86cGeorge Mount                case MOVED:
50722fe711207a37783dfa7142284b0ebe5bd503fbGeorge Mount                    callback.onItemRangeMoved(sender, listChanges.start, listChanges.to,
51722fe711207a37783dfa7142284b0ebe5bd503fbGeorge Mount                            listChanges.count);
525cd681c345db8f606d7d5a8662e20e059f21a86cGeorge Mount                    break;
535cd681c345db8f606d7d5a8662e20e059f21a86cGeorge Mount                case REMOVED:
54722fe711207a37783dfa7142284b0ebe5bd503fbGeorge Mount                    callback.onItemRangeRemoved(sender, listChanges.start, listChanges.count);
555cd681c345db8f606d7d5a8662e20e059f21a86cGeorge Mount                    break;
565cd681c345db8f606d7d5a8662e20e059f21a86cGeorge Mount                default:
57722fe711207a37783dfa7142284b0ebe5bd503fbGeorge Mount                    callback.onChanged(sender);
585cd681c345db8f606d7d5a8662e20e059f21a86cGeorge Mount                    break;
595cd681c345db8f606d7d5a8662e20e059f21a86cGeorge Mount            }
605cd681c345db8f606d7d5a8662e20e059f21a86cGeorge Mount        }
615cd681c345db8f606d7d5a8662e20e059f21a86cGeorge Mount    };
625cd681c345db8f606d7d5a8662e20e059f21a86cGeorge Mount
63c9a5d6f140f732ca0ff279a4b1ee315072e1c422George Mount    /**
64c9a5d6f140f732ca0ff279a4b1ee315072e1c422George Mount     * Notify registered callbacks that there was an unknown or whole-list change.
65c9a5d6f140f732ca0ff279a4b1ee315072e1c422George Mount     *
66c9a5d6f140f732ca0ff279a4b1ee315072e1c422George Mount     * @param list The list that changed.
67c9a5d6f140f732ca0ff279a4b1ee315072e1c422George Mount     */
685cd681c345db8f606d7d5a8662e20e059f21a86cGeorge Mount    public void notifyChanged(ObservableList list) {
695cd681c345db8f606d7d5a8662e20e059f21a86cGeorge Mount        notifyCallbacks(list, ALL, null);
705cd681c345db8f606d7d5a8662e20e059f21a86cGeorge Mount    }
715cd681c345db8f606d7d5a8662e20e059f21a86cGeorge Mount
72c9a5d6f140f732ca0ff279a4b1ee315072e1c422George Mount    /**
73c9a5d6f140f732ca0ff279a4b1ee315072e1c422George Mount     * Notify registered callbacks that some elements have changed.
74c9a5d6f140f732ca0ff279a4b1ee315072e1c422George Mount     *
75c9a5d6f140f732ca0ff279a4b1ee315072e1c422George Mount     * @param list The list that changed.
76c9a5d6f140f732ca0ff279a4b1ee315072e1c422George Mount     * @param start The index of the first changed element.
77c9a5d6f140f732ca0ff279a4b1ee315072e1c422George Mount     * @param count The number of changed elements.
78c9a5d6f140f732ca0ff279a4b1ee315072e1c422George Mount     */
795cd681c345db8f606d7d5a8662e20e059f21a86cGeorge Mount    public void notifyChanged(ObservableList list, int start, int count) {
805cd681c345db8f606d7d5a8662e20e059f21a86cGeorge Mount        ListChanges listChanges = acquire(start, 0, count);
815cd681c345db8f606d7d5a8662e20e059f21a86cGeorge Mount        notifyCallbacks(list, CHANGED, listChanges);
825cd681c345db8f606d7d5a8662e20e059f21a86cGeorge Mount    }
835cd681c345db8f606d7d5a8662e20e059f21a86cGeorge Mount
84c9a5d6f140f732ca0ff279a4b1ee315072e1c422George Mount    /**
85c9a5d6f140f732ca0ff279a4b1ee315072e1c422George Mount     * Notify registered callbacks that elements were inserted.
86c9a5d6f140f732ca0ff279a4b1ee315072e1c422George Mount     *
87c9a5d6f140f732ca0ff279a4b1ee315072e1c422George Mount     * @param list The list that changed.
88c9a5d6f140f732ca0ff279a4b1ee315072e1c422George Mount     * @param start The index where the elements were inserted.
89c9a5d6f140f732ca0ff279a4b1ee315072e1c422George Mount     * @param count The number of elements that were inserted.
90c9a5d6f140f732ca0ff279a4b1ee315072e1c422George Mount     */
915cd681c345db8f606d7d5a8662e20e059f21a86cGeorge Mount    public void notifyInserted(ObservableList list, int start, int count) {
925cd681c345db8f606d7d5a8662e20e059f21a86cGeorge Mount        ListChanges listChanges = acquire(start, 0, count);
935cd681c345db8f606d7d5a8662e20e059f21a86cGeorge Mount        notifyCallbacks(list, INSERTED, listChanges);
945cd681c345db8f606d7d5a8662e20e059f21a86cGeorge Mount    }
955cd681c345db8f606d7d5a8662e20e059f21a86cGeorge Mount
96c9a5d6f140f732ca0ff279a4b1ee315072e1c422George Mount    /**
97c9a5d6f140f732ca0ff279a4b1ee315072e1c422George Mount     * Notify registered callbacks that elements were moved.
98c9a5d6f140f732ca0ff279a4b1ee315072e1c422George Mount     *
99c9a5d6f140f732ca0ff279a4b1ee315072e1c422George Mount     * @param list The list that changed.
100c9a5d6f140f732ca0ff279a4b1ee315072e1c422George Mount     * @param from The index of the first element moved.
101c9a5d6f140f732ca0ff279a4b1ee315072e1c422George Mount     * @param to The index of where the element was moved to.
102c9a5d6f140f732ca0ff279a4b1ee315072e1c422George Mount     * @param count The number of elements moved.
103c9a5d6f140f732ca0ff279a4b1ee315072e1c422George Mount     */
1045cd681c345db8f606d7d5a8662e20e059f21a86cGeorge Mount    public void notifyMoved(ObservableList list, int from, int to, int count) {
1055cd681c345db8f606d7d5a8662e20e059f21a86cGeorge Mount        ListChanges listChanges = acquire(from, to, count);
1065cd681c345db8f606d7d5a8662e20e059f21a86cGeorge Mount        notifyCallbacks(list, MOVED, listChanges);
1075cd681c345db8f606d7d5a8662e20e059f21a86cGeorge Mount    }
1085cd681c345db8f606d7d5a8662e20e059f21a86cGeorge Mount
109c9a5d6f140f732ca0ff279a4b1ee315072e1c422George Mount    /**
110c9a5d6f140f732ca0ff279a4b1ee315072e1c422George Mount     * Notify registered callbacks that elements were deleted.
111c9a5d6f140f732ca0ff279a4b1ee315072e1c422George Mount     *
112c9a5d6f140f732ca0ff279a4b1ee315072e1c422George Mount     * @param list The list that changed.
113c9a5d6f140f732ca0ff279a4b1ee315072e1c422George Mount     * @param start The index of the first element to be removed.
114c9a5d6f140f732ca0ff279a4b1ee315072e1c422George Mount     * @param count The number of elements removed.
115c9a5d6f140f732ca0ff279a4b1ee315072e1c422George Mount     */
1165cd681c345db8f606d7d5a8662e20e059f21a86cGeorge Mount    public void notifyRemoved(ObservableList list, int start, int count) {
1175cd681c345db8f606d7d5a8662e20e059f21a86cGeorge Mount        ListChanges listChanges = acquire(start, 0, count);
1185cd681c345db8f606d7d5a8662e20e059f21a86cGeorge Mount        notifyCallbacks(list, REMOVED, listChanges);
1195cd681c345db8f606d7d5a8662e20e059f21a86cGeorge Mount    }
1205cd681c345db8f606d7d5a8662e20e059f21a86cGeorge Mount
1215cd681c345db8f606d7d5a8662e20e059f21a86cGeorge Mount    private static ListChanges acquire(int start, int to, int count) {
1225cd681c345db8f606d7d5a8662e20e059f21a86cGeorge Mount        ListChanges listChanges = sListChanges.acquire();
1235cd681c345db8f606d7d5a8662e20e059f21a86cGeorge Mount        if (listChanges == null) {
1245cd681c345db8f606d7d5a8662e20e059f21a86cGeorge Mount            listChanges = new ListChanges();
1255cd681c345db8f606d7d5a8662e20e059f21a86cGeorge Mount        }
1265cd681c345db8f606d7d5a8662e20e059f21a86cGeorge Mount        listChanges.start = start;
1275cd681c345db8f606d7d5a8662e20e059f21a86cGeorge Mount        listChanges.to = to;
1285cd681c345db8f606d7d5a8662e20e059f21a86cGeorge Mount        listChanges.count = count;
1295cd681c345db8f606d7d5a8662e20e059f21a86cGeorge Mount        return listChanges;
1305cd681c345db8f606d7d5a8662e20e059f21a86cGeorge Mount    }
1315cd681c345db8f606d7d5a8662e20e059f21a86cGeorge Mount
13265bf08e7cd0acc5e13ab131433e35981d4416a79George Mount    @Override
13365bf08e7cd0acc5e13ab131433e35981d4416a79George Mount    public synchronized void notifyCallbacks(ObservableList sender, int notificationType,
13465bf08e7cd0acc5e13ab131433e35981d4416a79George Mount            ListChanges listChanges) {
13565bf08e7cd0acc5e13ab131433e35981d4416a79George Mount        super.notifyCallbacks(sender, notificationType, listChanges);
13665bf08e7cd0acc5e13ab131433e35981d4416a79George Mount        if (listChanges != null) {
13765bf08e7cd0acc5e13ab131433e35981d4416a79George Mount            sListChanges.release(listChanges);
13865bf08e7cd0acc5e13ab131433e35981d4416a79George Mount        }
13965bf08e7cd0acc5e13ab131433e35981d4416a79George Mount    }
14065bf08e7cd0acc5e13ab131433e35981d4416a79George Mount
1415cd681c345db8f606d7d5a8662e20e059f21a86cGeorge Mount    public ListChangeRegistry() {
1425cd681c345db8f606d7d5a8662e20e059f21a86cGeorge Mount        super(NOTIFIER_CALLBACK);
1435cd681c345db8f606d7d5a8662e20e059f21a86cGeorge Mount    }
1445cd681c345db8f606d7d5a8662e20e059f21a86cGeorge Mount
1455cd681c345db8f606d7d5a8662e20e059f21a86cGeorge Mount    static class ListChanges {
1465cd681c345db8f606d7d5a8662e20e059f21a86cGeorge Mount        public int start;
1475cd681c345db8f606d7d5a8662e20e059f21a86cGeorge Mount        public int count;
1485cd681c345db8f606d7d5a8662e20e059f21a86cGeorge Mount        public int to;
1495cd681c345db8f606d7d5a8662e20e059f21a86cGeorge Mount    }
1505cd681c345db8f606d7d5a8662e20e059f21a86cGeorge Mount}
151