[go: nahoru, domu]

149c78900da0d43140fb602431fb93212bd7f6c70Chris Banes/*
249c78900da0d43140fb602431fb93212bd7f6c70Chris Banes * Copyright (C) 2013 The Android Open Source Project
349c78900da0d43140fb602431fb93212bd7f6c70Chris Banes *
449c78900da0d43140fb602431fb93212bd7f6c70Chris Banes * Licensed under the Apache License, Version 2.0 (the "License");
549c78900da0d43140fb602431fb93212bd7f6c70Chris Banes * you may not use this file except in compliance with the License.
649c78900da0d43140fb602431fb93212bd7f6c70Chris Banes * You may obtain a copy of the License at
749c78900da0d43140fb602431fb93212bd7f6c70Chris Banes *
849c78900da0d43140fb602431fb93212bd7f6c70Chris Banes *      http://www.apache.org/licenses/LICENSE-2.0
949c78900da0d43140fb602431fb93212bd7f6c70Chris Banes *
1049c78900da0d43140fb602431fb93212bd7f6c70Chris Banes * Unless required by applicable law or agreed to in writing, software
1149c78900da0d43140fb602431fb93212bd7f6c70Chris Banes * distributed under the License is distributed on an "AS IS" BASIS,
1249c78900da0d43140fb602431fb93212bd7f6c70Chris Banes * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
1349c78900da0d43140fb602431fb93212bd7f6c70Chris Banes * See the License for the specific language governing permissions and
1449c78900da0d43140fb602431fb93212bd7f6c70Chris Banes * limitations under the License.
1549c78900da0d43140fb602431fb93212bd7f6c70Chris Banes */
1649c78900da0d43140fb602431fb93212bd7f6c70Chris Banes
1749c78900da0d43140fb602431fb93212bd7f6c70Chris Banespackage android.support.v4.widget;
1849c78900da0d43140fb602431fb93212bd7f6c70Chris Banes
196142a54baae3289f734947c6b5375b12eb0fb722Chris Banesimport android.support.v4.view.GravityCompat;
206142a54baae3289f734947c6b5375b12eb0fb722Chris Banesimport android.support.v4.view.ViewCompat;
216142a54baae3289f734947c6b5375b12eb0fb722Chris Banesimport android.view.Gravity;
2249c78900da0d43140fb602431fb93212bd7f6c70Chris Banesimport android.view.View;
23322f8748f9d8de6f79345f660c859f163ad363b7Chris Banesimport android.view.WindowManager;
2449c78900da0d43140fb602431fb93212bd7f6c70Chris Banesimport android.widget.PopupWindow;
2549c78900da0d43140fb602431fb93212bd7f6c70Chris Banes
2649c78900da0d43140fb602431fb93212bd7f6c70Chris Banes/**
2749c78900da0d43140fb602431fb93212bd7f6c70Chris Banes * Helper for accessing features in PopupWindow introduced after API level 4
2849c78900da0d43140fb602431fb93212bd7f6c70Chris Banes * in a backwards compatible fashion.
2949c78900da0d43140fb602431fb93212bd7f6c70Chris Banes */
30c5847d13e40f5d52459f5c0dab32dc08f1a9a683Chris Banespublic final class PopupWindowCompat {
3149c78900da0d43140fb602431fb93212bd7f6c70Chris Banes    /**
3249c78900da0d43140fb602431fb93212bd7f6c70Chris Banes     * Interface for the full API.
3349c78900da0d43140fb602431fb93212bd7f6c70Chris Banes     */
3449c78900da0d43140fb602431fb93212bd7f6c70Chris Banes    interface PopupWindowImpl {
35322f8748f9d8de6f79345f660c859f163ad363b7Chris Banes        void showAsDropDown(PopupWindow popup, View anchor, int xoff, int yoff, int gravity);
36322f8748f9d8de6f79345f660c859f163ad363b7Chris Banes        void setOverlapAnchor(PopupWindow popupWindow, boolean overlapAnchor);
37322f8748f9d8de6f79345f660c859f163ad363b7Chris Banes        boolean getOverlapAnchor(PopupWindow popupWindow);
38322f8748f9d8de6f79345f660c859f163ad363b7Chris Banes        void setWindowLayoutType(PopupWindow popupWindow, int layoutType);
39322f8748f9d8de6f79345f660c859f163ad363b7Chris Banes        int getWindowLayoutType(PopupWindow popupWindow);
4049c78900da0d43140fb602431fb93212bd7f6c70Chris Banes    }
4149c78900da0d43140fb602431fb93212bd7f6c70Chris Banes
4249c78900da0d43140fb602431fb93212bd7f6c70Chris Banes    /**
4349c78900da0d43140fb602431fb93212bd7f6c70Chris Banes     * Interface implementation that doesn't use anything above v4 APIs.
4449c78900da0d43140fb602431fb93212bd7f6c70Chris Banes     */
4549c78900da0d43140fb602431fb93212bd7f6c70Chris Banes    static class BasePopupWindowImpl implements PopupWindowImpl {
4649c78900da0d43140fb602431fb93212bd7f6c70Chris Banes        @Override
4749c78900da0d43140fb602431fb93212bd7f6c70Chris Banes        public void showAsDropDown(PopupWindow popup, View anchor, int xoff, int yoff,
4849c78900da0d43140fb602431fb93212bd7f6c70Chris Banes                int gravity) {
496142a54baae3289f734947c6b5375b12eb0fb722Chris Banes            final int hgrav = GravityCompat.getAbsoluteGravity(gravity,
506142a54baae3289f734947c6b5375b12eb0fb722Chris Banes                    ViewCompat.getLayoutDirection(anchor)) & Gravity.HORIZONTAL_GRAVITY_MASK;
516142a54baae3289f734947c6b5375b12eb0fb722Chris Banes            if (hgrav == Gravity.RIGHT) {
526142a54baae3289f734947c6b5375b12eb0fb722Chris Banes                // Flip the location to align the right sides of the popup and
536142a54baae3289f734947c6b5375b12eb0fb722Chris Banes                // anchor instead of left.
546142a54baae3289f734947c6b5375b12eb0fb722Chris Banes                xoff -= (popup.getWidth() - anchor.getWidth());
556142a54baae3289f734947c6b5375b12eb0fb722Chris Banes            }
5649c78900da0d43140fb602431fb93212bd7f6c70Chris Banes            popup.showAsDropDown(anchor, xoff, yoff);
5749c78900da0d43140fb602431fb93212bd7f6c70Chris Banes        }
5844918a92e1d66a01a03063e2c5e68b2570f64b03Chris Banes
5944918a92e1d66a01a03063e2c5e68b2570f64b03Chris Banes        @Override
6044918a92e1d66a01a03063e2c5e68b2570f64b03Chris Banes        public void setOverlapAnchor(PopupWindow popupWindow, boolean overlapAnchor) {
6144918a92e1d66a01a03063e2c5e68b2570f64b03Chris Banes            // noop
6244918a92e1d66a01a03063e2c5e68b2570f64b03Chris Banes        }
6344918a92e1d66a01a03063e2c5e68b2570f64b03Chris Banes
6444918a92e1d66a01a03063e2c5e68b2570f64b03Chris Banes        @Override
6544918a92e1d66a01a03063e2c5e68b2570f64b03Chris Banes        public boolean getOverlapAnchor(PopupWindow popupWindow) {
6644918a92e1d66a01a03063e2c5e68b2570f64b03Chris Banes            return false;
6744918a92e1d66a01a03063e2c5e68b2570f64b03Chris Banes        }
68322f8748f9d8de6f79345f660c859f163ad363b7Chris Banes
69322f8748f9d8de6f79345f660c859f163ad363b7Chris Banes        @Override
70322f8748f9d8de6f79345f660c859f163ad363b7Chris Banes        public void setWindowLayoutType(PopupWindow popupWindow, int layoutType) {
71322f8748f9d8de6f79345f660c859f163ad363b7Chris Banes            // no-op
72322f8748f9d8de6f79345f660c859f163ad363b7Chris Banes        }
73322f8748f9d8de6f79345f660c859f163ad363b7Chris Banes
74322f8748f9d8de6f79345f660c859f163ad363b7Chris Banes        @Override
75322f8748f9d8de6f79345f660c859f163ad363b7Chris Banes        public int getWindowLayoutType(PopupWindow popupWindow) {
76322f8748f9d8de6f79345f660c859f163ad363b7Chris Banes            return 0;
77322f8748f9d8de6f79345f660c859f163ad363b7Chris Banes        }
78322f8748f9d8de6f79345f660c859f163ad363b7Chris Banes    }
79322f8748f9d8de6f79345f660c859f163ad363b7Chris Banes
80322f8748f9d8de6f79345f660c859f163ad363b7Chris Banes    /**
81322f8748f9d8de6f79345f660c859f163ad363b7Chris Banes     * Interface implementation that doesn't use anything above v4 APIs.
82322f8748f9d8de6f79345f660c859f163ad363b7Chris Banes     */
83322f8748f9d8de6f79345f660c859f163ad363b7Chris Banes    static class GingerbreadPopupWindowImpl extends BasePopupWindowImpl {
84322f8748f9d8de6f79345f660c859f163ad363b7Chris Banes        @Override
85322f8748f9d8de6f79345f660c859f163ad363b7Chris Banes        public void setWindowLayoutType(PopupWindow popupWindow, int layoutType) {
86322f8748f9d8de6f79345f660c859f163ad363b7Chris Banes            PopupWindowCompatGingerbread.setWindowLayoutType(popupWindow, layoutType);
87322f8748f9d8de6f79345f660c859f163ad363b7Chris Banes        }
88322f8748f9d8de6f79345f660c859f163ad363b7Chris Banes
89322f8748f9d8de6f79345f660c859f163ad363b7Chris Banes        @Override
90322f8748f9d8de6f79345f660c859f163ad363b7Chris Banes        public int getWindowLayoutType(PopupWindow popupWindow) {
91322f8748f9d8de6f79345f660c859f163ad363b7Chris Banes            return PopupWindowCompatGingerbread.getWindowLayoutType(popupWindow);
92322f8748f9d8de6f79345f660c859f163ad363b7Chris Banes        }
9349c78900da0d43140fb602431fb93212bd7f6c70Chris Banes    }
9449c78900da0d43140fb602431fb93212bd7f6c70Chris Banes
9549c78900da0d43140fb602431fb93212bd7f6c70Chris Banes    /**
9649c78900da0d43140fb602431fb93212bd7f6c70Chris Banes     * Interface implementation for devices with at least KitKat APIs.
9749c78900da0d43140fb602431fb93212bd7f6c70Chris Banes     */
98322f8748f9d8de6f79345f660c859f163ad363b7Chris Banes    static class KitKatPopupWindowImpl extends GingerbreadPopupWindowImpl {
9949c78900da0d43140fb602431fb93212bd7f6c70Chris Banes        @Override
10049c78900da0d43140fb602431fb93212bd7f6c70Chris Banes        public void showAsDropDown(PopupWindow popup, View anchor, int xoff, int yoff,
10149c78900da0d43140fb602431fb93212bd7f6c70Chris Banes                int gravity) {
10249c78900da0d43140fb602431fb93212bd7f6c70Chris Banes            PopupWindowCompatKitKat.showAsDropDown(popup, anchor, xoff, yoff, gravity);
10349c78900da0d43140fb602431fb93212bd7f6c70Chris Banes        }
10449c78900da0d43140fb602431fb93212bd7f6c70Chris Banes    }
10549c78900da0d43140fb602431fb93212bd7f6c70Chris Banes
10644918a92e1d66a01a03063e2c5e68b2570f64b03Chris Banes    static class Api21PopupWindowImpl extends KitKatPopupWindowImpl {
10744918a92e1d66a01a03063e2c5e68b2570f64b03Chris Banes        @Override
10844918a92e1d66a01a03063e2c5e68b2570f64b03Chris Banes        public void setOverlapAnchor(PopupWindow popupWindow, boolean overlapAnchor) {
10944918a92e1d66a01a03063e2c5e68b2570f64b03Chris Banes            PopupWindowCompatApi21.setOverlapAnchor(popupWindow, overlapAnchor);
11044918a92e1d66a01a03063e2c5e68b2570f64b03Chris Banes        }
11144918a92e1d66a01a03063e2c5e68b2570f64b03Chris Banes
11244918a92e1d66a01a03063e2c5e68b2570f64b03Chris Banes        @Override
11344918a92e1d66a01a03063e2c5e68b2570f64b03Chris Banes        public boolean getOverlapAnchor(PopupWindow popupWindow) {
11444918a92e1d66a01a03063e2c5e68b2570f64b03Chris Banes            return PopupWindowCompatApi21.getOverlapAnchor(popupWindow);
11544918a92e1d66a01a03063e2c5e68b2570f64b03Chris Banes        }
11644918a92e1d66a01a03063e2c5e68b2570f64b03Chris Banes    }
11744918a92e1d66a01a03063e2c5e68b2570f64b03Chris Banes
11844918a92e1d66a01a03063e2c5e68b2570f64b03Chris Banes    static class Api23PopupWindowImpl extends Api21PopupWindowImpl {
11944918a92e1d66a01a03063e2c5e68b2570f64b03Chris Banes        @Override
12044918a92e1d66a01a03063e2c5e68b2570f64b03Chris Banes        public void setOverlapAnchor(PopupWindow popupWindow, boolean overlapAnchor) {
12144918a92e1d66a01a03063e2c5e68b2570f64b03Chris Banes            PopupWindowCompatApi23.setOverlapAnchor(popupWindow, overlapAnchor);
12244918a92e1d66a01a03063e2c5e68b2570f64b03Chris Banes        }
12344918a92e1d66a01a03063e2c5e68b2570f64b03Chris Banes
12444918a92e1d66a01a03063e2c5e68b2570f64b03Chris Banes        @Override
12544918a92e1d66a01a03063e2c5e68b2570f64b03Chris Banes        public boolean getOverlapAnchor(PopupWindow popupWindow) {
12644918a92e1d66a01a03063e2c5e68b2570f64b03Chris Banes            return PopupWindowCompatApi23.getOverlapAnchor(popupWindow);
12744918a92e1d66a01a03063e2c5e68b2570f64b03Chris Banes        }
128322f8748f9d8de6f79345f660c859f163ad363b7Chris Banes
129322f8748f9d8de6f79345f660c859f163ad363b7Chris Banes        @Override
130322f8748f9d8de6f79345f660c859f163ad363b7Chris Banes        public void setWindowLayoutType(PopupWindow popupWindow, int layoutType) {
131322f8748f9d8de6f79345f660c859f163ad363b7Chris Banes            PopupWindowCompatApi23.setWindowLayoutType(popupWindow, layoutType);
132322f8748f9d8de6f79345f660c859f163ad363b7Chris Banes        }
133322f8748f9d8de6f79345f660c859f163ad363b7Chris Banes
134322f8748f9d8de6f79345f660c859f163ad363b7Chris Banes        @Override
135322f8748f9d8de6f79345f660c859f163ad363b7Chris Banes        public int getWindowLayoutType(PopupWindow popupWindow) {
136322f8748f9d8de6f79345f660c859f163ad363b7Chris Banes            return PopupWindowCompatApi23.getWindowLayoutType(popupWindow);
137322f8748f9d8de6f79345f660c859f163ad363b7Chris Banes        }
13844918a92e1d66a01a03063e2c5e68b2570f64b03Chris Banes    }
13944918a92e1d66a01a03063e2c5e68b2570f64b03Chris Banes
14049c78900da0d43140fb602431fb93212bd7f6c70Chris Banes    /**
14149c78900da0d43140fb602431fb93212bd7f6c70Chris Banes     * Select the correct implementation to use for the current platform.
14249c78900da0d43140fb602431fb93212bd7f6c70Chris Banes     */
14349c78900da0d43140fb602431fb93212bd7f6c70Chris Banes    static final PopupWindowImpl IMPL;
14449c78900da0d43140fb602431fb93212bd7f6c70Chris Banes    static {
14549c78900da0d43140fb602431fb93212bd7f6c70Chris Banes        final int version = android.os.Build.VERSION.SDK_INT;
14644918a92e1d66a01a03063e2c5e68b2570f64b03Chris Banes        if (version >= 23) {
14744918a92e1d66a01a03063e2c5e68b2570f64b03Chris Banes            IMPL = new Api23PopupWindowImpl();
14844918a92e1d66a01a03063e2c5e68b2570f64b03Chris Banes        } else if (version >= 21) {
14944918a92e1d66a01a03063e2c5e68b2570f64b03Chris Banes            IMPL = new Api21PopupWindowImpl();
15044918a92e1d66a01a03063e2c5e68b2570f64b03Chris Banes        } else if (version >= 19) {
15149c78900da0d43140fb602431fb93212bd7f6c70Chris Banes            IMPL = new KitKatPopupWindowImpl();
152322f8748f9d8de6f79345f660c859f163ad363b7Chris Banes        } else if (version >= 9) {
153322f8748f9d8de6f79345f660c859f163ad363b7Chris Banes            IMPL = new GingerbreadPopupWindowImpl();
15449c78900da0d43140fb602431fb93212bd7f6c70Chris Banes        } else {
15549c78900da0d43140fb602431fb93212bd7f6c70Chris Banes            IMPL = new BasePopupWindowImpl();
15649c78900da0d43140fb602431fb93212bd7f6c70Chris Banes        }
15749c78900da0d43140fb602431fb93212bd7f6c70Chris Banes    }
15849c78900da0d43140fb602431fb93212bd7f6c70Chris Banes
15949c78900da0d43140fb602431fb93212bd7f6c70Chris Banes    private PopupWindowCompat() {
16049c78900da0d43140fb602431fb93212bd7f6c70Chris Banes        // This class is not publicly instantiable.
16149c78900da0d43140fb602431fb93212bd7f6c70Chris Banes    }
16249c78900da0d43140fb602431fb93212bd7f6c70Chris Banes
16349c78900da0d43140fb602431fb93212bd7f6c70Chris Banes    /**
16449c78900da0d43140fb602431fb93212bd7f6c70Chris Banes     * <p>Display the content view in a popup window anchored to the bottom-left
16549c78900da0d43140fb602431fb93212bd7f6c70Chris Banes     * corner of the anchor view offset by the specified x and y coordinates.
16649c78900da0d43140fb602431fb93212bd7f6c70Chris Banes     * If there is not enough room on screen to show
16749c78900da0d43140fb602431fb93212bd7f6c70Chris Banes     * the popup in its entirety, this method tries to find a parent scroll
16849c78900da0d43140fb602431fb93212bd7f6c70Chris Banes     * view to scroll. If no parent scroll view can be scrolled, the bottom-left
16949c78900da0d43140fb602431fb93212bd7f6c70Chris Banes     * corner of the popup is pinned at the top left corner of the anchor view.</p>
17049c78900da0d43140fb602431fb93212bd7f6c70Chris Banes     * <p>If the view later scrolls to move <code>anchor</code> to a different
17149c78900da0d43140fb602431fb93212bd7f6c70Chris Banes     * location, the popup will be moved correspondingly.</p>
17249c78900da0d43140fb602431fb93212bd7f6c70Chris Banes     *
17349c78900da0d43140fb602431fb93212bd7f6c70Chris Banes     * @param popup the PopupWindow to show
17449c78900da0d43140fb602431fb93212bd7f6c70Chris Banes     * @param anchor the view on which to pin the popup window
17549c78900da0d43140fb602431fb93212bd7f6c70Chris Banes     * @param xoff A horizontal offset from the anchor in pixels
17649c78900da0d43140fb602431fb93212bd7f6c70Chris Banes     * @param yoff A vertical offset from the anchor in pixels
17749c78900da0d43140fb602431fb93212bd7f6c70Chris Banes     * @param gravity Alignment of the popup relative to the anchor
17849c78900da0d43140fb602431fb93212bd7f6c70Chris Banes     */
17949c78900da0d43140fb602431fb93212bd7f6c70Chris Banes    public static void showAsDropDown(PopupWindow popup, View anchor, int xoff, int yoff,
18049c78900da0d43140fb602431fb93212bd7f6c70Chris Banes            int gravity) {
18149c78900da0d43140fb602431fb93212bd7f6c70Chris Banes        IMPL.showAsDropDown(popup, anchor, xoff, yoff, gravity);
18249c78900da0d43140fb602431fb93212bd7f6c70Chris Banes    }
18344918a92e1d66a01a03063e2c5e68b2570f64b03Chris Banes
18444918a92e1d66a01a03063e2c5e68b2570f64b03Chris Banes    /**
18544918a92e1d66a01a03063e2c5e68b2570f64b03Chris Banes     * Sets whether the popup window should overlap its anchor view when
18644918a92e1d66a01a03063e2c5e68b2570f64b03Chris Banes     * displayed as a drop-down.
18744918a92e1d66a01a03063e2c5e68b2570f64b03Chris Banes     *
18844918a92e1d66a01a03063e2c5e68b2570f64b03Chris Banes     * @param overlapAnchor Whether the popup should overlap its anchor.
18944918a92e1d66a01a03063e2c5e68b2570f64b03Chris Banes     */
19044918a92e1d66a01a03063e2c5e68b2570f64b03Chris Banes    public static void setOverlapAnchor(PopupWindow popupWindow, boolean overlapAnchor) {
19144918a92e1d66a01a03063e2c5e68b2570f64b03Chris Banes        IMPL.setOverlapAnchor(popupWindow, overlapAnchor);
19244918a92e1d66a01a03063e2c5e68b2570f64b03Chris Banes    }
19344918a92e1d66a01a03063e2c5e68b2570f64b03Chris Banes
19444918a92e1d66a01a03063e2c5e68b2570f64b03Chris Banes    /**
19544918a92e1d66a01a03063e2c5e68b2570f64b03Chris Banes     * Returns whether the popup window should overlap its anchor view when
19644918a92e1d66a01a03063e2c5e68b2570f64b03Chris Banes     * displayed as a drop-down.
19744918a92e1d66a01a03063e2c5e68b2570f64b03Chris Banes     *
19844918a92e1d66a01a03063e2c5e68b2570f64b03Chris Banes     * @return Whether the popup should overlap its anchor.
19944918a92e1d66a01a03063e2c5e68b2570f64b03Chris Banes     */
20044918a92e1d66a01a03063e2c5e68b2570f64b03Chris Banes    public static boolean getOverlapAnchor(PopupWindow popupWindow) {
20144918a92e1d66a01a03063e2c5e68b2570f64b03Chris Banes        return IMPL.getOverlapAnchor(popupWindow);
20244918a92e1d66a01a03063e2c5e68b2570f64b03Chris Banes    }
203322f8748f9d8de6f79345f660c859f163ad363b7Chris Banes
204322f8748f9d8de6f79345f660c859f163ad363b7Chris Banes    /**
205322f8748f9d8de6f79345f660c859f163ad363b7Chris Banes     * Set the layout type for this window. This value will be passed through to
206322f8748f9d8de6f79345f660c859f163ad363b7Chris Banes     * {@link WindowManager.LayoutParams#type} therefore the value should match any value
207322f8748f9d8de6f79345f660c859f163ad363b7Chris Banes     * {@link WindowManager.LayoutParams#type} accepts.
208322f8748f9d8de6f79345f660c859f163ad363b7Chris Banes     *
209322f8748f9d8de6f79345f660c859f163ad363b7Chris Banes     * @param layoutType Layout type for this window.
210322f8748f9d8de6f79345f660c859f163ad363b7Chris Banes     *
211322f8748f9d8de6f79345f660c859f163ad363b7Chris Banes     * @see WindowManager.LayoutParams#type
212322f8748f9d8de6f79345f660c859f163ad363b7Chris Banes     */
213322f8748f9d8de6f79345f660c859f163ad363b7Chris Banes    public static void setWindowLayoutType(PopupWindow popupWindow, int layoutType) {
214322f8748f9d8de6f79345f660c859f163ad363b7Chris Banes        IMPL.setWindowLayoutType(popupWindow, layoutType);
215322f8748f9d8de6f79345f660c859f163ad363b7Chris Banes    }
216322f8748f9d8de6f79345f660c859f163ad363b7Chris Banes
217322f8748f9d8de6f79345f660c859f163ad363b7Chris Banes    /**
218322f8748f9d8de6f79345f660c859f163ad363b7Chris Banes     * Returns the layout type for this window.
219322f8748f9d8de6f79345f660c859f163ad363b7Chris Banes     *
220322f8748f9d8de6f79345f660c859f163ad363b7Chris Banes     * @see #setWindowLayoutType(PopupWindow popupWindow, int)
221322f8748f9d8de6f79345f660c859f163ad363b7Chris Banes     */
222322f8748f9d8de6f79345f660c859f163ad363b7Chris Banes    public static int getWindowLayoutType(PopupWindow popupWindow) {
223322f8748f9d8de6f79345f660c859f163ad363b7Chris Banes        return IMPL.getWindowLayoutType(popupWindow);
224322f8748f9d8de6f79345f660c859f163ad363b7Chris Banes    }
22549c78900da0d43140fb602431fb93212bd7f6c70Chris Banes}
226