Home | History | Annotate | Download | only in browse
      1 /*
      2  * Copyright (C) 2012 Google Inc.
      3  * Licensed to The Android Open Source Project.
      4  *
      5  * Licensed under the Apache License, Version 2.0 (the "License");
      6  * you may not use this file except in compliance with the License.
      7  * You may obtain a copy of the License at
      8  *
      9  *      http://www.apache.org/licenses/LICENSE-2.0
     10  *
     11  * Unless required by applicable law or agreed to in writing, software
     12  * distributed under the License is distributed on an "AS IS" BASIS,
     13  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     14  * See the License for the specific language governing permissions and
     15  * limitations under the License.
     16  */
     17 
     18 package com.android.mail.browse;
     19 
     20 import android.content.Context;
     21 import android.view.Gravity;
     22 import android.view.LayoutInflater;
     23 import android.view.View;
     24 import android.view.ViewGroup;
     25 import android.widget.Adapter;
     26 import android.widget.CursorAdapter;
     27 
     28 import com.android.mail.ui.ConversationViewFragment;
     29 import com.android.mail.utils.LogUtils;
     30 
     31 public abstract class ConversationOverlayItem {
     32     private int mHeight;  // in px
     33     private int mTop;  // in px
     34     private boolean mNeedsMeasure;
     35 
     36     public static final String LOG_TAG = ConversationViewFragment.LAYOUT_TAG;
     37 
     38     private int mPosition;
     39 
     40     /**
     41      * @see Adapter#getItemViewType(int)
     42      */
     43     public abstract int getType();
     44     /**
     45      * Inflate and perform one-time initialization on a view for later binding.
     46      */
     47     public abstract View createView(Context context, LayoutInflater inflater,
     48             ViewGroup parent);
     49 
     50     /**
     51      * @see CursorAdapter#bindView(View, Context, android.database.Cursor)
     52      * @param v a view to bind to
     53      * @param measureOnly true iff we are binding this view only to measure its height (so items
     54      * know they can cut certain corners that do not affect a view's height)
     55      */
     56     public abstract void bindView(View v, boolean measureOnly);
     57     /**
     58      * Returns true if this overlay view is meant to be positioned right on top of the overlay
     59      * below. This special positioning allows {@link ConversationContainer} to stack overlays
     60      * together even when zoomed into a conversation, when the overlay spacers spread farther
     61      * apart.
     62      */
     63     public abstract boolean isContiguous();
     64 
     65     /**
     66      * Returns true if this overlay view is in its expanded state.
     67      */
     68     public boolean isExpanded() {
     69         return true;
     70     }
     71 
     72     public int getGravity() {
     73         return Gravity.BOTTOM;
     74     }
     75 
     76     /**
     77      * This method's behavior is critical and requires some 'splainin.
     78      * <p>
     79      * Subclasses that return a zero-size height to the {@link ConversationContainer} will
     80      * cause the scrolling/recycling logic there to remove any matching view from the container.
     81      * The item should switch to returning a non-zero height when its view should re-appear.
     82      * <p>
     83      * It's imperative that this method stay in sync with the current height of the HTML spacer
     84      * that matches this overlay.
     85      */
     86     public int getHeight() {
     87         return mHeight;
     88     }
     89 
     90     /**
     91      * Set a new height.
     92      *
     93      * @param h a new height
     94      * @return true if the value changed
     95      */
     96     public boolean setHeight(int h) {
     97         LogUtils.i(LOG_TAG, "IN setHeight=%dpx of overlay item: %s", h, this);
     98         if (mHeight != h) {
     99             mHeight = h;
    100             mNeedsMeasure = true;
    101             return true;
    102         }
    103         return false;
    104     }
    105 
    106     public int getTop() {
    107         return mTop;
    108     }
    109 
    110     public void setTop(int top) {
    111         mTop = top;
    112     }
    113 
    114     public boolean isMeasurementValid() {
    115         return !mNeedsMeasure;
    116     }
    117 
    118     public void markMeasurementValid() {
    119         mNeedsMeasure = false;
    120     }
    121 
    122     public void invalidateMeasurement() {
    123         mNeedsMeasure = true;
    124     }
    125 
    126     public boolean canBecomeSnapHeader() {
    127         return false;
    128     }
    129 
    130     public boolean canPushSnapHeader() {
    131         return false;
    132     }
    133 
    134     public boolean belongsToMessage(ConversationMessage message) {
    135         return false;
    136     }
    137 
    138     public void setMessage(ConversationMessage message) {
    139     }
    140 
    141     /**
    142      * Given a view that is already bound to this item, force the view to re-render the item's
    143      * current model data. This is typically called after a data model update, to update the
    144      * affected view in-place.
    145      */
    146     public void onModelUpdated(View v) {
    147     }
    148 
    149     public void setPosition(int position) {
    150         mPosition = position;
    151     }
    152 
    153     public int getPosition() {
    154         return mPosition;
    155     }
    156 
    157     /**
    158      * This is a hack. Now that one view can update the
    159      * state of another view, we need a mechanism when the
    160      * view's associated item changes to update the state of the
    161      * view. Typically, classes that override this class should not
    162      * override this method.<br><br>
    163      *
    164      * This method is used by
    165      * {@link com.android.mail.browse.ConversationViewAdapter.BorderItem}
    166      * to update the height of the border based on whether the neighboring messages
    167      * are collapsed or expanded.<br><br>
    168      *
    169      * It is also used by {@link com.android.mail.browse.ConversationViewAdapter.MessageHeaderItem}
    170      * in the case where the snap header is tapped to collapse the message but the
    171      * message header is still on screen. Since the message header is still on screen,
    172      * it does not get bound but will get a rebind.<br><br>
    173      *
    174      * The only other way to handle this case would be to call
    175      * {@link com.android.mail.browse.ConversationViewAdapter#notifyDataSetChanged()}
    176      * but that makes the entire screen flicker since the entire adapter performs
    177      * a layout of the every item.
    178      * @param view the view to be re-bound
    179      */
    180     public void rebindView(View view) {
    181         // DO NOTHING
    182     }
    183 }
    184