1/*
2 * Copyright (C) 2008 Esmertec AG.
3 * Copyright (C) 2008 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
18package com.android.mms.model;
19
20import java.util.ArrayList;
21
22import android.util.Config;
23import android.util.Log;
24
25import com.android.mms.layout.LayoutManager;
26import com.android.mms.layout.LayoutParameters;
27
28public class LayoutModel extends Model {
29    private static final String TAG = SlideModel.TAG;
30    private static final boolean DEBUG = false;
31    private static final boolean LOCAL_LOGV = DEBUG ? Config.LOGD : Config.LOGV;
32
33    public static final String IMAGE_REGION_ID = "Image";
34    public static final String TEXT_REGION_ID  = "Text";
35
36    public static final int LAYOUT_BOTTOM_TEXT = 0;
37    public static final int LAYOUT_TOP_TEXT    = 1;
38    public static final int DEFAULT_LAYOUT_TYPE = LAYOUT_BOTTOM_TEXT;
39
40    private int mLayoutType = DEFAULT_LAYOUT_TYPE;
41    private RegionModel mRootLayout;
42    private RegionModel mImageRegion;
43    private RegionModel mTextRegion;
44    private ArrayList<RegionModel> mNonStdRegions;
45    private LayoutParameters mLayoutParams;
46
47    public LayoutModel() {
48        mLayoutParams = LayoutManager.getInstance().getLayoutParameters();
49        // Create default root-layout and regions.
50        createDefaultRootLayout();
51        createDefaultImageRegion();
52        createDefaultTextRegion();
53    }
54
55    public LayoutModel(RegionModel rootLayout, ArrayList<RegionModel> regions) {
56        mLayoutParams = LayoutManager.getInstance().getLayoutParameters();
57        mRootLayout = rootLayout;
58        mNonStdRegions = new ArrayList<RegionModel>();
59
60        for (RegionModel r : regions) {
61            String rId = r.getRegionId();
62            if (rId.equals(IMAGE_REGION_ID)) {
63                mImageRegion = r;
64            } else if (rId.equals(TEXT_REGION_ID)) {
65                mTextRegion = r;
66            } else {
67                if (LOCAL_LOGV) {
68                    Log.v(TAG, "Found non-standard region: " + rId);
69                }
70                mNonStdRegions.add(r);
71            }
72        }
73
74        validateLayouts();
75    }
76
77    private void createDefaultRootLayout() {
78        mRootLayout = new RegionModel(null, 0, 0, mLayoutParams.getWidth(),
79                                                  mLayoutParams.getHeight());
80    }
81
82    private void createDefaultImageRegion() {
83        if (mRootLayout == null) {
84            throw new IllegalStateException("Root-Layout uninitialized.");
85        }
86
87        mImageRegion = new RegionModel(IMAGE_REGION_ID, 0, 0,
88                mRootLayout.getWidth(), mLayoutParams.getImageHeight());
89    }
90
91    private void createDefaultTextRegion() {
92        if (mRootLayout == null) {
93            throw new IllegalStateException("Root-Layout uninitialized.");
94        }
95
96        mTextRegion = new RegionModel(
97                TEXT_REGION_ID, 0, mLayoutParams.getImageHeight(),
98                mRootLayout.getWidth(), mLayoutParams.getTextHeight());
99    }
100
101    private void validateLayouts() {
102        if (mRootLayout == null) {
103            createDefaultRootLayout();
104        }
105
106        if (mImageRegion == null) {
107            createDefaultImageRegion();
108        }
109
110        if (mTextRegion == null) {
111            createDefaultTextRegion();
112        }
113        // LayoutModel will re-construct when orientation changes, so we need to
114        // initialize mLayoutType here. Otherwise, the mLayoutType is alway default
115        // value (LAYOUT_BOTTOM_TEXT) after LayoutModel re-construct.
116        mLayoutType =
117                (mImageRegion.getTop() == 0) ? LAYOUT_BOTTOM_TEXT : LAYOUT_TOP_TEXT;
118    }
119
120    public RegionModel getRootLayout() {
121        return mRootLayout;
122    }
123
124    public void setRootLayout(RegionModel rootLayout) {
125        mRootLayout = rootLayout;
126    }
127
128    public RegionModel getImageRegion() {
129        return mImageRegion;
130    }
131
132    public void setImageRegion(RegionModel imageRegion) {
133        mImageRegion = imageRegion;
134    }
135
136    public RegionModel getTextRegion() {
137        return mTextRegion;
138    }
139
140    public void setTextRegion(RegionModel textRegion) {
141        mTextRegion = textRegion;
142    }
143
144    /**
145     * Get all regions except root-layout. The result is READ-ONLY.
146     */
147    public ArrayList<RegionModel> getRegions() {
148        ArrayList<RegionModel> regions = new ArrayList<RegionModel>();
149        if (mImageRegion != null) {
150            regions.add(mImageRegion);
151        }
152        if (mTextRegion != null) {
153            regions.add(mTextRegion);
154        }
155        return regions;
156    }
157
158    public RegionModel findRegionById(String rId) {
159        if (IMAGE_REGION_ID.equals(rId)) {
160            return mImageRegion;
161        } else if (TEXT_REGION_ID.equals(rId)) {
162            return mTextRegion;
163        } else {
164            for (RegionModel r : mNonStdRegions) {
165                if (r.getRegionId().equals(rId)) {
166                    return r;
167                }
168            }
169
170            if (LOCAL_LOGV) {
171                Log.v(TAG, "Region not found: " + rId);
172            }
173            return null;
174        }
175    }
176
177    public int getLayoutWidth() {
178        return mRootLayout.getWidth();
179    }
180
181    public int getLayoutHeight() {
182        return mRootLayout.getHeight();
183    }
184
185    public String getBackgroundColor() {
186        return mRootLayout.getBackgroundColor();
187    }
188
189    public void changeTo(int layout) {
190        if (mRootLayout == null) {
191            throw new IllegalStateException("Root-Layout uninitialized.");
192        }
193
194        if (mLayoutParams == null) {
195            mLayoutParams = LayoutManager.getInstance().getLayoutParameters();
196        }
197
198        if (mLayoutType != layout) {
199            switch (layout) {
200                case LAYOUT_BOTTOM_TEXT: {
201                    mImageRegion.setTop(0);
202                    mTextRegion.setTop(mLayoutParams.getImageHeight());
203                    mLayoutType = layout;
204                    notifyModelChanged(true);
205                }
206                break;
207                case LAYOUT_TOP_TEXT: {
208                    mImageRegion.setTop(mLayoutParams.getTextHeight());
209                    mTextRegion.setTop(0);
210                    mLayoutType = layout;
211                    notifyModelChanged(true);
212                }
213                break;
214                default: {
215                    Log.w(TAG, "Unknown layout type: " + layout);
216                }
217            }
218        } else {
219            if (LOCAL_LOGV) {
220                Log.v(TAG, "Skip changing layout.");
221            }
222        }
223    }
224
225    public int getLayoutType() {
226        return mLayoutType;
227    }
228
229    @Override
230    protected void registerModelChangedObserverInDescendants(
231            IModelChangedObserver observer) {
232        if (mRootLayout != null) {
233            mRootLayout.registerModelChangedObserver(observer);
234        }
235
236        if (mImageRegion != null) {
237            mImageRegion.registerModelChangedObserver(observer);
238        }
239
240        if (mTextRegion != null) {
241            mTextRegion.registerModelChangedObserver(observer);
242        }
243    }
244
245    @Override
246    protected void unregisterModelChangedObserverInDescendants(
247            IModelChangedObserver observer) {
248        if (mRootLayout != null) {
249            mRootLayout.unregisterModelChangedObserver(observer);
250        }
251
252        if (mImageRegion != null) {
253            mImageRegion.unregisterModelChangedObserver(observer);
254        }
255
256        if (mTextRegion != null) {
257            mTextRegion.unregisterModelChangedObserver(observer);
258        }
259    }
260
261    @Override
262    protected void unregisterAllModelChangedObserversInDescendants() {
263        if (mRootLayout != null) {
264            mRootLayout.unregisterAllModelChangedObservers();
265        }
266
267        if (mImageRegion != null) {
268            mImageRegion.unregisterAllModelChangedObservers();
269        }
270
271        if (mTextRegion != null) {
272            mTextRegion.unregisterAllModelChangedObservers();
273        }
274    }
275}
276