BackStackRecord.java revision eedc67283a5a49dce86c625e54596dfdea9465a7
1/*
2 * Copyright (C) 2011 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 *      http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17package android.support.v4.app;
18
19import android.os.Parcel;
20import android.os.Parcelable;
21import android.text.TextUtils;
22import android.util.Log;
23
24import java.io.FileDescriptor;
25import java.io.PrintWriter;
26import java.util.ArrayList;
27
28final class BackStackState implements Parcelable {
29    final int[] mOps;
30    final int mTransition;
31    final int mTransitionStyle;
32    final String mName;
33    final int mIndex;
34    final int mBreadCrumbTitleRes;
35    final CharSequence mBreadCrumbTitleText;
36    final int mBreadCrumbShortTitleRes;
37    final CharSequence mBreadCrumbShortTitleText;
38
39    public BackStackState(FragmentManagerImpl fm, BackStackRecord bse) {
40        int numRemoved = 0;
41        BackStackRecord.Op op = bse.mHead;
42        while (op != null) {
43            if (op.removed != null) numRemoved += op.removed.size();
44            op = op.next;
45        }
46        mOps = new int[bse.mNumOp*5 + numRemoved];
47
48        if (!bse.mAddToBackStack) {
49            throw new IllegalStateException("Not on back stack");
50        }
51
52        op = bse.mHead;
53        int pos = 0;
54        while (op != null) {
55            mOps[pos++] = op.cmd;
56            mOps[pos++] = op.fragment.mIndex;
57            mOps[pos++] = op.enterAnim;
58            mOps[pos++] = op.exitAnim;
59            if (op.removed != null) {
60                final int N = op.removed.size();
61                mOps[pos++] = N;
62                for (int i=0; i<N; i++) {
63                    mOps[pos++] = op.removed.get(i).mIndex;
64                }
65            } else {
66                mOps[pos++] = 0;
67            }
68            op = op.next;
69        }
70        mTransition = bse.mTransition;
71        mTransitionStyle = bse.mTransitionStyle;
72        mName = bse.mName;
73        mIndex = bse.mIndex;
74        mBreadCrumbTitleRes = bse.mBreadCrumbTitleRes;
75        mBreadCrumbTitleText = bse.mBreadCrumbTitleText;
76        mBreadCrumbShortTitleRes = bse.mBreadCrumbShortTitleRes;
77        mBreadCrumbShortTitleText = bse.mBreadCrumbShortTitleText;
78    }
79
80    public BackStackState(Parcel in) {
81        mOps = in.createIntArray();
82        mTransition = in.readInt();
83        mTransitionStyle = in.readInt();
84        mName = in.readString();
85        mIndex = in.readInt();
86        mBreadCrumbTitleRes = in.readInt();
87        mBreadCrumbTitleText = TextUtils.CHAR_SEQUENCE_CREATOR.createFromParcel(in);
88        mBreadCrumbShortTitleRes = in.readInt();
89        mBreadCrumbShortTitleText = TextUtils.CHAR_SEQUENCE_CREATOR.createFromParcel(in);
90    }
91
92    public BackStackRecord instantiate(FragmentManagerImpl fm) {
93        BackStackRecord bse = new BackStackRecord(fm);
94        int pos = 0;
95        while (pos < mOps.length) {
96            BackStackRecord.Op op = new BackStackRecord.Op();
97            op.cmd = mOps[pos++];
98            if (FragmentManagerImpl.DEBUG) Log.v(FragmentManagerImpl.TAG,
99                    "BSE " + bse + " set base fragment #" + mOps[pos]);
100            Fragment f = fm.mActive.get(mOps[pos++]);
101            op.fragment = f;
102            op.enterAnim = mOps[pos++];
103            op.exitAnim = mOps[pos++];
104            final int N = mOps[pos++];
105            if (N > 0) {
106                op.removed = new ArrayList<Fragment>(N);
107                for (int i=0; i<N; i++) {
108                    if (FragmentManagerImpl.DEBUG) Log.v(FragmentManagerImpl.TAG,
109                            "BSE " + bse + " set remove fragment #" + mOps[pos]);
110                    Fragment r = fm.mActive.get(mOps[pos++]);
111                    op.removed.add(r);
112                }
113            }
114            bse.addOp(op);
115        }
116        bse.mTransition = mTransition;
117        bse.mTransitionStyle = mTransitionStyle;
118        bse.mName = mName;
119        bse.mIndex = mIndex;
120        bse.mAddToBackStack = true;
121        bse.mBreadCrumbTitleRes = mBreadCrumbTitleRes;
122        bse.mBreadCrumbTitleText = mBreadCrumbTitleText;
123        bse.mBreadCrumbShortTitleRes = mBreadCrumbShortTitleRes;
124        bse.mBreadCrumbShortTitleText = mBreadCrumbShortTitleText;
125        bse.bumpBackStackNesting(1);
126        return bse;
127    }
128
129    public int describeContents() {
130        return 0;
131    }
132
133    public void writeToParcel(Parcel dest, int flags) {
134        dest.writeIntArray(mOps);
135        dest.writeInt(mTransition);
136        dest.writeInt(mTransitionStyle);
137        dest.writeString(mName);
138        dest.writeInt(mIndex);
139        dest.writeInt(mBreadCrumbTitleRes);
140        TextUtils.writeToParcel(mBreadCrumbTitleText, dest, 0);
141        dest.writeInt(mBreadCrumbShortTitleRes);
142        TextUtils.writeToParcel(mBreadCrumbShortTitleText, dest, 0);
143    }
144
145    public static final Parcelable.Creator<BackStackState> CREATOR
146            = new Parcelable.Creator<BackStackState>() {
147        public BackStackState createFromParcel(Parcel in) {
148            return new BackStackState(in);
149        }
150
151        public BackStackState[] newArray(int size) {
152            return new BackStackState[size];
153        }
154    };
155}
156
157/**
158 * @hide Entry of an operation on the fragment back stack.
159 */
160final class BackStackRecord extends FragmentTransaction implements
161        FragmentManager.BackStackEntry, Runnable {
162    static final String TAG = "BackStackEntry";
163
164    final FragmentManagerImpl mManager;
165
166    static final int OP_NULL = 0;
167    static final int OP_ADD = 1;
168    static final int OP_REPLACE = 2;
169    static final int OP_REMOVE = 3;
170    static final int OP_HIDE = 4;
171    static final int OP_SHOW = 5;
172    static final int OP_DETACH = 6;
173    static final int OP_ATTACH = 7;
174
175    static final class Op {
176        Op next;
177        Op prev;
178        int cmd;
179        Fragment fragment;
180        int enterAnim;
181        int exitAnim;
182        ArrayList<Fragment> removed;
183    }
184
185    Op mHead;
186    Op mTail;
187    int mNumOp;
188    int mEnterAnim;
189    int mExitAnim;
190    int mTransition;
191    int mTransitionStyle;
192    boolean mAddToBackStack;
193    boolean mAllowAddToBackStack = true;
194    String mName;
195    boolean mCommitted;
196    int mIndex;
197
198    int mBreadCrumbTitleRes;
199    CharSequence mBreadCrumbTitleText;
200    int mBreadCrumbShortTitleRes;
201    CharSequence mBreadCrumbShortTitleText;
202
203    public void dump(String prefix, FileDescriptor fd, PrintWriter writer, String[] args) {
204        writer.print(prefix); writer.print("mName="); writer.print(mName);
205                writer.print(" mIndex="); writer.print(mIndex);
206                writer.print(" mCommitted="); writer.println(mCommitted);
207        if (mTransition != FragmentTransaction.TRANSIT_NONE) {
208            writer.print(prefix); writer.print("mTransition=#");
209                    writer.print(Integer.toHexString(mTransition));
210                    writer.print(" mTransitionStyle=#");
211                    writer.println(Integer.toHexString(mTransitionStyle));
212        }
213        if (mEnterAnim != 0 || mExitAnim !=0) {
214            writer.print(prefix); writer.print("mEnterAnim=#");
215                    writer.print(Integer.toHexString(mEnterAnim));
216                    writer.print(" mExitAnim=#");
217                    writer.println(Integer.toHexString(mExitAnim));
218        }
219        if (mBreadCrumbTitleRes != 0 || mBreadCrumbTitleText != null) {
220            writer.print(prefix); writer.print("mBreadCrumbTitleRes=#");
221                    writer.print(Integer.toHexString(mBreadCrumbTitleRes));
222                    writer.print(" mBreadCrumbTitleText=");
223                    writer.println(mBreadCrumbTitleText);
224        }
225        if (mBreadCrumbShortTitleRes != 0 || mBreadCrumbShortTitleText != null) {
226            writer.print(prefix); writer.print("mBreadCrumbShortTitleRes=#");
227                    writer.print(Integer.toHexString(mBreadCrumbShortTitleRes));
228                    writer.print(" mBreadCrumbShortTitleText=");
229                    writer.println(mBreadCrumbShortTitleText);
230        }
231
232        if (mHead != null) {
233            writer.print(prefix); writer.println("Operations:");
234            String innerPrefix = prefix + "    ";
235            Op op = mHead;
236            int num = 0;
237            while (op != null) {
238                writer.print(prefix); writer.print("  Op #"); writer.print(num);
239                        writer.println(":");
240                writer.print(innerPrefix); writer.print("cmd="); writer.print(op.cmd);
241                        writer.print(" fragment="); writer.println(op.fragment);
242                if (op.enterAnim != 0 || op.exitAnim != 0) {
243                    writer.print(prefix); writer.print("enterAnim="); writer.print(op.enterAnim);
244                            writer.print(" exitAnim="); writer.println(op.exitAnim);
245                }
246                if (op.removed != null && op.removed.size() > 0) {
247                    for (int i=0; i<op.removed.size(); i++) {
248                        writer.print(innerPrefix);
249                        if (op.removed.size() == 1) {
250                            writer.print("Removed: ");
251                        } else {
252                            writer.println("Removed:");
253                            writer.print(innerPrefix); writer.print("  #"); writer.print(num);
254                                    writer.print(": ");
255                        }
256                        writer.println(op.removed.get(i));
257                    }
258                }
259                op = op.next;
260            }
261        }
262    }
263
264    public BackStackRecord(FragmentManagerImpl manager) {
265        mManager = manager;
266    }
267
268    public int getId() {
269        return mIndex;
270    }
271
272    public int getBreadCrumbTitleRes() {
273        return mBreadCrumbTitleRes;
274    }
275
276    public int getBreadCrumbShortTitleRes() {
277        return mBreadCrumbShortTitleRes;
278    }
279
280    public CharSequence getBreadCrumbTitle() {
281        if (mBreadCrumbTitleRes != 0) {
282            return mManager.mActivity.getText(mBreadCrumbTitleRes);
283        }
284        return mBreadCrumbTitleText;
285    }
286
287    public CharSequence getBreadCrumbShortTitle() {
288        if (mBreadCrumbShortTitleRes != 0) {
289            return mManager.mActivity.getText(mBreadCrumbShortTitleRes);
290        }
291        return mBreadCrumbShortTitleText;
292    }
293
294    void addOp(Op op) {
295        if (mHead == null) {
296            mHead = mTail = op;
297        } else {
298            op.prev = mTail;
299            mTail.next = op;
300            mTail = op;
301        }
302        op.enterAnim = mEnterAnim;
303        op.exitAnim = mExitAnim;
304        mNumOp++;
305    }
306
307    public FragmentTransaction add(Fragment fragment, String tag) {
308        doAddOp(0, fragment, tag, OP_ADD);
309        return this;
310    }
311
312    public FragmentTransaction add(int containerViewId, Fragment fragment) {
313        doAddOp(containerViewId, fragment, null, OP_ADD);
314        return this;
315    }
316
317    public FragmentTransaction add(int containerViewId, Fragment fragment, String tag) {
318        doAddOp(containerViewId, fragment, tag, OP_ADD);
319        return this;
320    }
321
322    private void doAddOp(int containerViewId, Fragment fragment, String tag, int opcmd) {
323        if (fragment.mImmediateActivity != null) {
324            throw new IllegalStateException("Fragment already added: " + fragment);
325        }
326        fragment.mImmediateActivity = mManager.mActivity;
327        fragment.mFragmentManager = mManager;
328
329        if (tag != null) {
330            if (fragment.mTag != null && !tag.equals(fragment.mTag)) {
331                throw new IllegalStateException("Can't change tag of fragment "
332                        + fragment + ": was " + fragment.mTag
333                        + " now " + tag);
334            }
335            fragment.mTag = tag;
336        }
337
338        if (containerViewId != 0) {
339            if (fragment.mFragmentId != 0 && fragment.mFragmentId != containerViewId) {
340                throw new IllegalStateException("Can't change container ID of fragment "
341                        + fragment + ": was " + fragment.mFragmentId
342                        + " now " + containerViewId);
343            }
344            fragment.mContainerId = fragment.mFragmentId = containerViewId;
345        }
346
347        Op op = new Op();
348        op.cmd = opcmd;
349        op.fragment = fragment;
350        addOp(op);
351    }
352
353    public FragmentTransaction replace(int containerViewId, Fragment fragment) {
354        return replace(containerViewId, fragment, null);
355    }
356
357    public FragmentTransaction replace(int containerViewId, Fragment fragment, String tag) {
358        if (containerViewId == 0) {
359            throw new IllegalArgumentException("Must use non-zero containerViewId");
360        }
361
362        doAddOp(containerViewId, fragment, tag, OP_REPLACE);
363        return this;
364    }
365
366    public FragmentTransaction remove(Fragment fragment) {
367        if (fragment.mImmediateActivity == null) {
368            throw new IllegalStateException("Fragment not added: " + fragment);
369        }
370        fragment.mImmediateActivity = null;
371
372        Op op = new Op();
373        op.cmd = OP_REMOVE;
374        op.fragment = fragment;
375        addOp(op);
376
377        return this;
378    }
379
380    public FragmentTransaction hide(Fragment fragment) {
381        if (fragment.mImmediateActivity == null) {
382            throw new IllegalStateException("Fragment not added: " + fragment);
383        }
384
385        Op op = new Op();
386        op.cmd = OP_HIDE;
387        op.fragment = fragment;
388        addOp(op);
389
390        return this;
391    }
392
393    public FragmentTransaction show(Fragment fragment) {
394        if (fragment.mImmediateActivity == null) {
395            throw new IllegalStateException("Fragment not added: " + fragment);
396        }
397
398        Op op = new Op();
399        op.cmd = OP_SHOW;
400        op.fragment = fragment;
401        addOp(op);
402
403        return this;
404    }
405
406    public FragmentTransaction detach(Fragment fragment) {
407        //if (fragment.mImmediateActivity == null) {
408        //    throw new IllegalStateException("Fragment not added: " + fragment);
409        //}
410
411        Op op = new Op();
412        op.cmd = OP_DETACH;
413        op.fragment = fragment;
414        addOp(op);
415
416        return this;
417    }
418
419    public FragmentTransaction attach(Fragment fragment) {
420        //if (fragment.mImmediateActivity == null) {
421        //    throw new IllegalStateException("Fragment not added: " + fragment);
422        //}
423
424        Op op = new Op();
425        op.cmd = OP_ATTACH;
426        op.fragment = fragment;
427        addOp(op);
428
429        return this;
430    }
431
432    public FragmentTransaction setCustomAnimations(int enter, int exit) {
433        mEnterAnim = enter;
434        mExitAnim = exit;
435        return this;
436    }
437
438    public FragmentTransaction setTransition(int transition) {
439        mTransition = transition;
440        return this;
441    }
442
443    public FragmentTransaction setTransitionStyle(int styleRes) {
444        mTransitionStyle = styleRes;
445        return this;
446    }
447
448    public FragmentTransaction addToBackStack(String name) {
449        if (!mAllowAddToBackStack) {
450            throw new IllegalStateException(
451                    "This FragmentTransaction is not allowed to be added to the back stack.");
452        }
453        mAddToBackStack = true;
454        mName = name;
455        return this;
456    }
457
458    public boolean isAddToBackStackAllowed() {
459        return mAllowAddToBackStack;
460    }
461
462    public FragmentTransaction disallowAddToBackStack() {
463        if (mAddToBackStack) {
464            throw new IllegalStateException(
465                    "This transaction is already being added to the back stack");
466        }
467        mAllowAddToBackStack = false;
468        return this;
469    }
470
471    public FragmentTransaction setBreadCrumbTitle(int res) {
472        mBreadCrumbTitleRes = res;
473        mBreadCrumbTitleText = null;
474        return this;
475    }
476
477    public FragmentTransaction setBreadCrumbTitle(CharSequence text) {
478        mBreadCrumbTitleRes = 0;
479        mBreadCrumbTitleText = text;
480        return this;
481    }
482
483    public FragmentTransaction setBreadCrumbShortTitle(int res) {
484        mBreadCrumbShortTitleRes = res;
485        mBreadCrumbShortTitleText = null;
486        return this;
487    }
488
489    public FragmentTransaction setBreadCrumbShortTitle(CharSequence text) {
490        mBreadCrumbShortTitleRes = 0;
491        mBreadCrumbShortTitleText = text;
492        return this;
493    }
494
495    void bumpBackStackNesting(int amt) {
496        if (!mAddToBackStack) {
497            return;
498        }
499        if (FragmentManagerImpl.DEBUG) Log.v(TAG, "Bump nesting in " + this
500                + " by " + amt);
501        Op op = mHead;
502        while (op != null) {
503            op.fragment.mBackStackNesting += amt;
504            if (FragmentManagerImpl.DEBUG) Log.v(TAG, "Bump nesting of "
505                    + op.fragment + " to " + op.fragment.mBackStackNesting);
506            if (op.removed != null) {
507                for (int i=op.removed.size()-1; i>=0; i--) {
508                    Fragment r = op.removed.get(i);
509                    r.mBackStackNesting += amt;
510                    if (FragmentManagerImpl.DEBUG) Log.v(TAG, "Bump nesting of "
511                            + r + " to " + r.mBackStackNesting);
512                }
513            }
514            op = op.next;
515        }
516    }
517
518    public int commit() {
519        return commitInternal(false);
520    }
521
522    public int commitAllowingStateLoss() {
523        return commitInternal(true);
524    }
525
526    int commitInternal(boolean allowStateLoss) {
527        if (mCommitted) throw new IllegalStateException("commit already called");
528        if (FragmentManagerImpl.DEBUG) Log.v(TAG, "Commit: " + this);
529        mCommitted = true;
530        if (mAddToBackStack) {
531            mIndex = mManager.allocBackStackIndex(this);
532        } else {
533            mIndex = -1;
534        }
535        mManager.enqueueAction(this, allowStateLoss);
536        return mIndex;
537    }
538
539    public void run() {
540        if (FragmentManagerImpl.DEBUG) Log.v(TAG, "Run: " + this);
541
542        if (mAddToBackStack) {
543            if (mIndex < 0) {
544                throw new IllegalStateException("addToBackStack() called after commit()");
545            }
546        }
547
548        bumpBackStackNesting(1);
549
550        Op op = mHead;
551        while (op != null) {
552            switch (op.cmd) {
553                case OP_ADD: {
554                    Fragment f = op.fragment;
555                    f.mNextAnim = op.enterAnim;
556                    mManager.addFragment(f, false);
557                } break;
558                case OP_REPLACE: {
559                    Fragment f = op.fragment;
560                    if (mManager.mAdded != null) {
561                        for (int i=0; i<mManager.mAdded.size(); i++) {
562                            Fragment old = mManager.mAdded.get(i);
563                            if (FragmentManagerImpl.DEBUG) Log.v(TAG,
564                                    "OP_REPLACE: adding=" + f + " old=" + old);
565                            if (old.mContainerId == f.mContainerId) {
566                                if (op.removed == null) {
567                                    op.removed = new ArrayList<Fragment>();
568                                }
569                                op.removed.add(old);
570                                old.mNextAnim = op.exitAnim;
571                                if (mAddToBackStack) {
572                                    old.mBackStackNesting += 1;
573                                    if (FragmentManagerImpl.DEBUG) Log.v(TAG, "Bump nesting of "
574                                            + old + " to " + old.mBackStackNesting);
575                                }
576                                mManager.removeFragment(old, mTransition, mTransitionStyle);
577                            }
578                        }
579                    }
580                    f.mNextAnim = op.enterAnim;
581                    mManager.addFragment(f, false);
582                } break;
583                case OP_REMOVE: {
584                    Fragment f = op.fragment;
585                    f.mNextAnim = op.exitAnim;
586                    mManager.removeFragment(f, mTransition, mTransitionStyle);
587                } break;
588                case OP_HIDE: {
589                    Fragment f = op.fragment;
590                    f.mNextAnim = op.exitAnim;
591                    mManager.hideFragment(f, mTransition, mTransitionStyle);
592                } break;
593                case OP_SHOW: {
594                    Fragment f = op.fragment;
595                    f.mNextAnim = op.enterAnim;
596                    mManager.showFragment(f, mTransition, mTransitionStyle);
597                } break;
598                case OP_DETACH: {
599                    Fragment f = op.fragment;
600                    f.mNextAnim = op.exitAnim;
601                    mManager.detachFragment(f, mTransition, mTransitionStyle);
602                } break;
603                case OP_ATTACH: {
604                    Fragment f = op.fragment;
605                    f.mNextAnim = op.enterAnim;
606                    mManager.attachFragment(f, mTransition, mTransitionStyle);
607                } break;
608                default: {
609                    throw new IllegalArgumentException("Unknown cmd: " + op.cmd);
610                }
611            }
612
613            op = op.next;
614        }
615
616        mManager.moveToState(mManager.mCurState, mTransition,
617                mTransitionStyle, true);
618
619        if (mAddToBackStack) {
620            mManager.addBackStackState(this);
621        }
622    }
623
624    public void popFromBackStack(boolean doStateMove) {
625        if (FragmentManagerImpl.DEBUG) Log.v(TAG, "popFromBackStack: " + this);
626
627        bumpBackStackNesting(-1);
628
629        Op op = mTail;
630        while (op != null) {
631            switch (op.cmd) {
632                case OP_ADD: {
633                    Fragment f = op.fragment;
634                    f.mImmediateActivity = null;
635                    mManager.removeFragment(f,
636                            FragmentManagerImpl.reverseTransit(mTransition),
637                            mTransitionStyle);
638                } break;
639                case OP_REPLACE: {
640                    Fragment f = op.fragment;
641                    f.mImmediateActivity = null;
642                    mManager.removeFragment(f,
643                            FragmentManagerImpl.reverseTransit(mTransition),
644                            mTransitionStyle);
645                    if (op.removed != null) {
646                        for (int i=0; i<op.removed.size(); i++) {
647                            Fragment old = op.removed.get(i);
648                            f.mImmediateActivity = mManager.mActivity;
649                            mManager.addFragment(old, false);
650                        }
651                    }
652                } break;
653                case OP_REMOVE: {
654                    Fragment f = op.fragment;
655                    f.mImmediateActivity = mManager.mActivity;
656                    mManager.addFragment(f, false);
657                } break;
658                case OP_HIDE: {
659                    Fragment f = op.fragment;
660                    mManager.showFragment(f,
661                            FragmentManagerImpl.reverseTransit(mTransition), mTransitionStyle);
662                } break;
663                case OP_SHOW: {
664                    Fragment f = op.fragment;
665                    mManager.hideFragment(f,
666                            FragmentManagerImpl.reverseTransit(mTransition), mTransitionStyle);
667                } break;
668                case OP_DETACH: {
669                    Fragment f = op.fragment;
670                    mManager.attachFragment(f,
671                            FragmentManagerImpl.reverseTransit(mTransition), mTransitionStyle);
672                } break;
673                case OP_ATTACH: {
674                    Fragment f = op.fragment;
675                    mManager.detachFragment(f,
676                            FragmentManagerImpl.reverseTransit(mTransition), mTransitionStyle);
677                } break;
678                default: {
679                    throw new IllegalArgumentException("Unknown cmd: " + op.cmd);
680                }
681            }
682
683            op = op.prev;
684        }
685
686        if (doStateMove) {
687            mManager.moveToState(mManager.mCurState,
688                    FragmentManagerImpl.reverseTransit(mTransition), mTransitionStyle, true);
689        }
690
691        if (mIndex >= 0) {
692            mManager.freeBackStackIndex(mIndex);
693            mIndex = -1;
694        }
695    }
696
697    public String getName() {
698        return mName;
699    }
700
701    public int getTransition() {
702        return mTransition;
703    }
704
705    public int getTransitionStyle() {
706        return mTransitionStyle;
707    }
708
709    public boolean isEmpty() {
710        return mNumOp == 0;
711    }
712}
713