Home | History | Annotate | Download | only in models
      1 /*
      2  * Copyright (C) 2010 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 
     17 package com.android.hierarchyviewerlib.models;
     18 
     19 import com.android.hierarchyviewerlib.device.ViewNode;
     20 import com.android.hierarchyviewerlib.device.Window;
     21 import com.android.hierarchyviewerlib.ui.util.DrawableViewNode;
     22 import com.android.hierarchyviewerlib.ui.util.DrawableViewNode.Point;
     23 import com.android.hierarchyviewerlib.ui.util.DrawableViewNode.Rectangle;
     24 
     25 import java.util.ArrayList;
     26 
     27 public class TreeViewModel {
     28     public static final double MAX_ZOOM = 2;
     29 
     30     public static final double MIN_ZOOM = 0.2;
     31 
     32     private Window mWindow;
     33 
     34     private DrawableViewNode mTree;
     35 
     36     private DrawableViewNode mSelectedNode;
     37 
     38     private Rectangle mViewport;
     39 
     40     private double mZoom;
     41 
     42     private final ArrayList<ITreeChangeListener> mTreeChangeListeners =
     43             new ArrayList<ITreeChangeListener>();
     44 
     45     private static TreeViewModel sModel;
     46 
     47     public static TreeViewModel getModel() {
     48         if (sModel == null) {
     49             sModel = new TreeViewModel();
     50         }
     51         return sModel;
     52     }
     53 
     54     public void setData(Window window, ViewNode viewNode) {
     55         synchronized (this) {
     56             if (mTree != null) {
     57                 mTree.viewNode.dispose();
     58             }
     59             this.mWindow = window;
     60             if (viewNode == null) {
     61                 mTree = null;
     62             } else {
     63                 mTree = new DrawableViewNode(viewNode);
     64                 mTree.setLeft();
     65                 mTree.placeRoot();
     66             }
     67             mViewport = null;
     68             mZoom = 1;
     69             mSelectedNode = null;
     70         }
     71         notifyTreeChanged();
     72     }
     73 
     74     public void setSelection(DrawableViewNode selectedNode) {
     75         synchronized (this) {
     76             this.mSelectedNode = selectedNode;
     77         }
     78         notifySelectionChanged();
     79     }
     80 
     81     public void setViewport(Rectangle viewport) {
     82         synchronized (this) {
     83             this.mViewport = viewport;
     84         }
     85         notifyViewportChanged();
     86     }
     87 
     88     public void setZoom(double newZoom) {
     89         Point zoomPoint = null;
     90         synchronized (this) {
     91             if (mTree != null && mViewport != null) {
     92                 zoomPoint =
     93                         new Point(mViewport.x + mViewport.width / 2, mViewport.y + mViewport.height / 2);
     94             }
     95         }
     96         zoomOnPoint(newZoom, zoomPoint);
     97     }
     98 
     99     public void zoomOnPoint(double newZoom, Point zoomPoint) {
    100         synchronized (this) {
    101             if (mTree != null && this.mViewport != null) {
    102                 if (newZoom < MIN_ZOOM) {
    103                     newZoom = MIN_ZOOM;
    104                 }
    105                 if (newZoom > MAX_ZOOM) {
    106                     newZoom = MAX_ZOOM;
    107                 }
    108                 mViewport.x = zoomPoint.x - (zoomPoint.x - mViewport.x) * mZoom / newZoom;
    109                 mViewport.y = zoomPoint.y - (zoomPoint.y - mViewport.y) * mZoom / newZoom;
    110                 mViewport.width = mViewport.width * mZoom / newZoom;
    111                 mViewport.height = mViewport.height * mZoom / newZoom;
    112                 mZoom = newZoom;
    113             }
    114         }
    115         notifyZoomChanged();
    116     }
    117 
    118     public DrawableViewNode getTree() {
    119         synchronized (this) {
    120             return mTree;
    121         }
    122     }
    123 
    124     public Window getWindow() {
    125         synchronized (this) {
    126             return mWindow;
    127         }
    128     }
    129 
    130     public Rectangle getViewport() {
    131         synchronized (this) {
    132             return mViewport;
    133         }
    134     }
    135 
    136     public double getZoom() {
    137         synchronized (this) {
    138             return mZoom;
    139         }
    140     }
    141 
    142     public DrawableViewNode getSelection() {
    143         synchronized (this) {
    144             return mSelectedNode;
    145         }
    146     }
    147 
    148     public static interface ITreeChangeListener {
    149         public void treeChanged();
    150 
    151         public void selectionChanged();
    152 
    153         public void viewportChanged();
    154 
    155         public void zoomChanged();
    156     }
    157 
    158     private ITreeChangeListener[] getTreeChangeListenerList() {
    159         ITreeChangeListener[] listeners = null;
    160         synchronized (mTreeChangeListeners) {
    161             if (mTreeChangeListeners.size() == 0) {
    162                 return null;
    163             }
    164             listeners =
    165                     mTreeChangeListeners.toArray(new ITreeChangeListener[mTreeChangeListeners.size()]);
    166         }
    167         return listeners;
    168     }
    169 
    170     public void notifyTreeChanged() {
    171         ITreeChangeListener[] listeners = getTreeChangeListenerList();
    172         if (listeners != null) {
    173             for (int i = 0; i < listeners.length; i++) {
    174                 listeners[i].treeChanged();
    175             }
    176         }
    177     }
    178 
    179     public void notifySelectionChanged() {
    180         ITreeChangeListener[] listeners = getTreeChangeListenerList();
    181         if (listeners != null) {
    182             for (int i = 0; i < listeners.length; i++) {
    183                 listeners[i].selectionChanged();
    184             }
    185         }
    186     }
    187 
    188     public void notifyViewportChanged() {
    189         ITreeChangeListener[] listeners = getTreeChangeListenerList();
    190         if (listeners != null) {
    191             for (int i = 0; i < listeners.length; i++) {
    192                 listeners[i].viewportChanged();
    193             }
    194         }
    195     }
    196 
    197     public void notifyZoomChanged() {
    198         ITreeChangeListener[] listeners = getTreeChangeListenerList();
    199         if (listeners != null) {
    200             for (int i = 0; i < listeners.length; i++) {
    201                 listeners[i].zoomChanged();
    202             }
    203         }
    204     }
    205 
    206     public void addTreeChangeListener(ITreeChangeListener listener) {
    207         synchronized (mTreeChangeListeners) {
    208             mTreeChangeListeners.add(listener);
    209         }
    210     }
    211 
    212     public void removeTreeChangeListener(ITreeChangeListener listener) {
    213         synchronized (mTreeChangeListeners) {
    214             mTreeChangeListeners.remove(listener);
    215         }
    216     }
    217 }
    218