1731066a59e10ddc7bb6c95d0b91b3e0e11e10396Craig Stout/* 2731066a59e10ddc7bb6c95d0b91b3e0e11e10396Craig Stout * Copyright (C) 2014 The Android Open Source Project 3731066a59e10ddc7bb6c95d0b91b3e0e11e10396Craig Stout * 4731066a59e10ddc7bb6c95d0b91b3e0e11e10396Craig Stout * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except 5731066a59e10ddc7bb6c95d0b91b3e0e11e10396Craig Stout * in compliance with the License. You may obtain a copy of the License at 6731066a59e10ddc7bb6c95d0b91b3e0e11e10396Craig Stout * 7731066a59e10ddc7bb6c95d0b91b3e0e11e10396Craig Stout * http://www.apache.org/licenses/LICENSE-2.0 8731066a59e10ddc7bb6c95d0b91b3e0e11e10396Craig Stout * 9731066a59e10ddc7bb6c95d0b91b3e0e11e10396Craig Stout * Unless required by applicable law or agreed to in writing, software distributed under the License 10731066a59e10ddc7bb6c95d0b91b3e0e11e10396Craig Stout * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express 11731066a59e10ddc7bb6c95d0b91b3e0e11e10396Craig Stout * or implied. See the License for the specific language governing permissions and limitations under 12731066a59e10ddc7bb6c95d0b91b3e0e11e10396Craig Stout * the License. 13731066a59e10ddc7bb6c95d0b91b3e0e11e10396Craig Stout */ 14731066a59e10ddc7bb6c95d0b91b3e0e11e10396Craig Stoutpackage android.support.v17.leanback.widget; 15731066a59e10ddc7bb6c95d0b91b3e0e11e10396Craig Stout 16731066a59e10ddc7bb6c95d0b91b3e0e11e10396Craig Stoutimport android.content.Context; 17731066a59e10ddc7bb6c95d0b91b3e0e11e10396Craig Stoutimport android.graphics.drawable.Drawable; 18731066a59e10ddc7bb6c95d0b91b3e0e11e10396Craig Stoutimport android.support.v17.leanback.R; 19731066a59e10ddc7bb6c95d0b91b3e0e11e10396Craig Stoutimport android.util.AttributeSet; 20731066a59e10ddc7bb6c95d0b91b3e0e11e10396Craig Stoutimport android.view.LayoutInflater; 21731066a59e10ddc7bb6c95d0b91b3e0e11e10396Craig Stoutimport android.view.View; 22731066a59e10ddc7bb6c95d0b91b3e0e11e10396Craig Stoutimport android.widget.FrameLayout; 23731066a59e10ddc7bb6c95d0b91b3e0e11e10396Craig Stoutimport android.widget.ImageView; 24731066a59e10ddc7bb6c95d0b91b3e0e11e10396Craig Stoutimport android.widget.TextView; 25731066a59e10ddc7bb6c95d0b91b3e0e11e10396Craig Stout 26a373804d10f93a9488adc35cf6ce44dce09b3778Dake Guimport static android.support.v17.leanback.widget.TitleViewAdapter.BRANDING_VIEW_VISIBLE; 27a373804d10f93a9488adc35cf6ce44dce09b3778Dake Guimport static android.support.v17.leanback.widget.TitleViewAdapter.SEARCH_VIEW_VISIBLE; 28a373804d10f93a9488adc35cf6ce44dce09b3778Dake Guimport static android.support.v17.leanback.widget.TitleViewAdapter.FULL_VIEW_VISIBLE; 29a373804d10f93a9488adc35cf6ce44dce09b3778Dake Gu 30731066a59e10ddc7bb6c95d0b91b3e0e11e10396Craig Stout/** 31731066a59e10ddc7bb6c95d0b91b3e0e11e10396Craig Stout * Title view for a leanback fragment. 32731066a59e10ddc7bb6c95d0b91b3e0e11e10396Craig Stout */ 33a373804d10f93a9488adc35cf6ce44dce09b3778Dake Gupublic class TitleView extends FrameLayout implements TitleViewAdapter.Provider { 34731066a59e10ddc7bb6c95d0b91b3e0e11e10396Craig Stout 35731066a59e10ddc7bb6c95d0b91b3e0e11e10396Craig Stout private ImageView mBadgeView; 36731066a59e10ddc7bb6c95d0b91b3e0e11e10396Craig Stout private TextView mTextView; 37731066a59e10ddc7bb6c95d0b91b3e0e11e10396Craig Stout private SearchOrbView mSearchOrbView; 387350fc450e5850b7a3dddff6d63fb87bd24886ddsusnata private int flags = FULL_VIEW_VISIBLE; 39977f0610fcfc783a9ed91ccb08387472b743ce63Dake Gu private boolean mHasSearchListener = false; 40731066a59e10ddc7bb6c95d0b91b3e0e11e10396Craig Stout 41a373804d10f93a9488adc35cf6ce44dce09b3778Dake Gu private final TitleViewAdapter mTitleViewAdapter = new TitleViewAdapter() { 42a373804d10f93a9488adc35cf6ce44dce09b3778Dake Gu @Override 43a373804d10f93a9488adc35cf6ce44dce09b3778Dake Gu public View getSearchAffordanceView() { 44a373804d10f93a9488adc35cf6ce44dce09b3778Dake Gu return TitleView.this.getSearchAffordanceView(); 45a373804d10f93a9488adc35cf6ce44dce09b3778Dake Gu } 46a373804d10f93a9488adc35cf6ce44dce09b3778Dake Gu 47a373804d10f93a9488adc35cf6ce44dce09b3778Dake Gu @Override 48a373804d10f93a9488adc35cf6ce44dce09b3778Dake Gu public void setOnSearchClickedListener(View.OnClickListener listener) { 49a373804d10f93a9488adc35cf6ce44dce09b3778Dake Gu TitleView.this.setOnSearchClickedListener(listener); 50a373804d10f93a9488adc35cf6ce44dce09b3778Dake Gu } 51a373804d10f93a9488adc35cf6ce44dce09b3778Dake Gu 52a373804d10f93a9488adc35cf6ce44dce09b3778Dake Gu @Override 53a373804d10f93a9488adc35cf6ce44dce09b3778Dake Gu public void setAnimationEnabled(boolean enable) { 54a373804d10f93a9488adc35cf6ce44dce09b3778Dake Gu TitleView.this.enableAnimation(enable); 55a373804d10f93a9488adc35cf6ce44dce09b3778Dake Gu } 56a373804d10f93a9488adc35cf6ce44dce09b3778Dake Gu 57a373804d10f93a9488adc35cf6ce44dce09b3778Dake Gu @Override 58a373804d10f93a9488adc35cf6ce44dce09b3778Dake Gu public Drawable getBadgeDrawable() { 59a373804d10f93a9488adc35cf6ce44dce09b3778Dake Gu return TitleView.this.getBadgeDrawable(); 60a373804d10f93a9488adc35cf6ce44dce09b3778Dake Gu } 61a373804d10f93a9488adc35cf6ce44dce09b3778Dake Gu 62a373804d10f93a9488adc35cf6ce44dce09b3778Dake Gu @Override 63a373804d10f93a9488adc35cf6ce44dce09b3778Dake Gu public SearchOrbView.Colors getSearchAffordanceColors() { 64a373804d10f93a9488adc35cf6ce44dce09b3778Dake Gu return TitleView.this.getSearchAffordanceColors(); 65a373804d10f93a9488adc35cf6ce44dce09b3778Dake Gu } 66a373804d10f93a9488adc35cf6ce44dce09b3778Dake Gu 67a373804d10f93a9488adc35cf6ce44dce09b3778Dake Gu @Override 68a373804d10f93a9488adc35cf6ce44dce09b3778Dake Gu public CharSequence getTitle() { 69a373804d10f93a9488adc35cf6ce44dce09b3778Dake Gu return TitleView.this.getTitle(); 70a373804d10f93a9488adc35cf6ce44dce09b3778Dake Gu } 71a373804d10f93a9488adc35cf6ce44dce09b3778Dake Gu 72a373804d10f93a9488adc35cf6ce44dce09b3778Dake Gu @Override 73a373804d10f93a9488adc35cf6ce44dce09b3778Dake Gu public void setBadgeDrawable(Drawable drawable) { 74a373804d10f93a9488adc35cf6ce44dce09b3778Dake Gu TitleView.this.setBadgeDrawable(drawable); 75a373804d10f93a9488adc35cf6ce44dce09b3778Dake Gu } 76a373804d10f93a9488adc35cf6ce44dce09b3778Dake Gu 77a373804d10f93a9488adc35cf6ce44dce09b3778Dake Gu @Override 78a373804d10f93a9488adc35cf6ce44dce09b3778Dake Gu public void setSearchAffordanceColors(SearchOrbView.Colors colors) { 79a373804d10f93a9488adc35cf6ce44dce09b3778Dake Gu TitleView.this.setSearchAffordanceColors(colors); 80a373804d10f93a9488adc35cf6ce44dce09b3778Dake Gu } 81a373804d10f93a9488adc35cf6ce44dce09b3778Dake Gu 82a373804d10f93a9488adc35cf6ce44dce09b3778Dake Gu @Override 83a373804d10f93a9488adc35cf6ce44dce09b3778Dake Gu public void setTitle(CharSequence titleText) { 84a373804d10f93a9488adc35cf6ce44dce09b3778Dake Gu TitleView.this.setTitle(titleText); 85a373804d10f93a9488adc35cf6ce44dce09b3778Dake Gu } 86a373804d10f93a9488adc35cf6ce44dce09b3778Dake Gu 87a373804d10f93a9488adc35cf6ce44dce09b3778Dake Gu @Override 88a373804d10f93a9488adc35cf6ce44dce09b3778Dake Gu public void updateComponentsVisibility(int flags) { 89a373804d10f93a9488adc35cf6ce44dce09b3778Dake Gu TitleView.this.updateComponentsVisibility(flags); 90a373804d10f93a9488adc35cf6ce44dce09b3778Dake Gu } 91a373804d10f93a9488adc35cf6ce44dce09b3778Dake Gu }; 92a373804d10f93a9488adc35cf6ce44dce09b3778Dake Gu 93731066a59e10ddc7bb6c95d0b91b3e0e11e10396Craig Stout public TitleView(Context context) { 94731066a59e10ddc7bb6c95d0b91b3e0e11e10396Craig Stout this(context, null); 95731066a59e10ddc7bb6c95d0b91b3e0e11e10396Craig Stout } 96731066a59e10ddc7bb6c95d0b91b3e0e11e10396Craig Stout 97731066a59e10ddc7bb6c95d0b91b3e0e11e10396Craig Stout public TitleView(Context context, AttributeSet attrs) { 985a59bde085588f95dc067bd1ed64a940f355343cbulic this(context, attrs, R.attr.browseTitleViewStyle); 99731066a59e10ddc7bb6c95d0b91b3e0e11e10396Craig Stout } 100731066a59e10ddc7bb6c95d0b91b3e0e11e10396Craig Stout 1015a59bde085588f95dc067bd1ed64a940f355343cbulic public TitleView(Context context, AttributeSet attrs, int defStyleAttr) { 1025a59bde085588f95dc067bd1ed64a940f355343cbulic super(context, attrs, defStyleAttr); 103731066a59e10ddc7bb6c95d0b91b3e0e11e10396Craig Stout 104731066a59e10ddc7bb6c95d0b91b3e0e11e10396Craig Stout LayoutInflater inflater = LayoutInflater.from(context); 105731066a59e10ddc7bb6c95d0b91b3e0e11e10396Craig Stout View rootView = inflater.inflate(R.layout.lb_title_view, this); 106731066a59e10ddc7bb6c95d0b91b3e0e11e10396Craig Stout 107e7246ef136ed686d8caf339d4d1fd8e37b499c6aCraig Stout mBadgeView = (ImageView) rootView.findViewById(R.id.title_badge); 108e7246ef136ed686d8caf339d4d1fd8e37b499c6aCraig Stout mTextView = (TextView) rootView.findViewById(R.id.title_text); 109e7246ef136ed686d8caf339d4d1fd8e37b499c6aCraig Stout mSearchOrbView = (SearchOrbView) rootView.findViewById(R.id.title_orb); 110731066a59e10ddc7bb6c95d0b91b3e0e11e10396Craig Stout 111731066a59e10ddc7bb6c95d0b91b3e0e11e10396Craig Stout setClipToPadding(false); 112731066a59e10ddc7bb6c95d0b91b3e0e11e10396Craig Stout setClipChildren(false); 113731066a59e10ddc7bb6c95d0b91b3e0e11e10396Craig Stout } 114731066a59e10ddc7bb6c95d0b91b3e0e11e10396Craig Stout 115731066a59e10ddc7bb6c95d0b91b3e0e11e10396Craig Stout /** 116731066a59e10ddc7bb6c95d0b91b3e0e11e10396Craig Stout * Sets the title text. 117731066a59e10ddc7bb6c95d0b91b3e0e11e10396Craig Stout */ 118a373804d10f93a9488adc35cf6ce44dce09b3778Dake Gu public void setTitle(CharSequence titleText) { 119731066a59e10ddc7bb6c95d0b91b3e0e11e10396Craig Stout mTextView.setText(titleText); 1207350fc450e5850b7a3dddff6d63fb87bd24886ddsusnata updateBadgeVisibility(); 121731066a59e10ddc7bb6c95d0b91b3e0e11e10396Craig Stout } 122731066a59e10ddc7bb6c95d0b91b3e0e11e10396Craig Stout 123731066a59e10ddc7bb6c95d0b91b3e0e11e10396Craig Stout /** 124731066a59e10ddc7bb6c95d0b91b3e0e11e10396Craig Stout * Returns the title text. 125731066a59e10ddc7bb6c95d0b91b3e0e11e10396Craig Stout */ 126731066a59e10ddc7bb6c95d0b91b3e0e11e10396Craig Stout public CharSequence getTitle() { 127731066a59e10ddc7bb6c95d0b91b3e0e11e10396Craig Stout return mTextView.getText(); 128731066a59e10ddc7bb6c95d0b91b3e0e11e10396Craig Stout } 129731066a59e10ddc7bb6c95d0b91b3e0e11e10396Craig Stout 130731066a59e10ddc7bb6c95d0b91b3e0e11e10396Craig Stout /** 131731066a59e10ddc7bb6c95d0b91b3e0e11e10396Craig Stout * Sets the badge drawable. 132731066a59e10ddc7bb6c95d0b91b3e0e11e10396Craig Stout * If non-null, the drawable is displayed instead of the title text. 133731066a59e10ddc7bb6c95d0b91b3e0e11e10396Craig Stout */ 134731066a59e10ddc7bb6c95d0b91b3e0e11e10396Craig Stout public void setBadgeDrawable(Drawable drawable) { 135731066a59e10ddc7bb6c95d0b91b3e0e11e10396Craig Stout mBadgeView.setImageDrawable(drawable); 1367350fc450e5850b7a3dddff6d63fb87bd24886ddsusnata updateBadgeVisibility(); 137731066a59e10ddc7bb6c95d0b91b3e0e11e10396Craig Stout } 138731066a59e10ddc7bb6c95d0b91b3e0e11e10396Craig Stout 139731066a59e10ddc7bb6c95d0b91b3e0e11e10396Craig Stout /** 140731066a59e10ddc7bb6c95d0b91b3e0e11e10396Craig Stout * Returns the badge drawable. 141731066a59e10ddc7bb6c95d0b91b3e0e11e10396Craig Stout */ 142731066a59e10ddc7bb6c95d0b91b3e0e11e10396Craig Stout public Drawable getBadgeDrawable() { 143731066a59e10ddc7bb6c95d0b91b3e0e11e10396Craig Stout return mBadgeView.getDrawable(); 144731066a59e10ddc7bb6c95d0b91b3e0e11e10396Craig Stout } 145731066a59e10ddc7bb6c95d0b91b3e0e11e10396Craig Stout 146731066a59e10ddc7bb6c95d0b91b3e0e11e10396Craig Stout /** 147731066a59e10ddc7bb6c95d0b91b3e0e11e10396Craig Stout * Sets the listener to be called when the search affordance is clicked. 148731066a59e10ddc7bb6c95d0b91b3e0e11e10396Craig Stout */ 149731066a59e10ddc7bb6c95d0b91b3e0e11e10396Craig Stout public void setOnSearchClickedListener(View.OnClickListener listener) { 150977f0610fcfc783a9ed91ccb08387472b743ce63Dake Gu mHasSearchListener = listener != null; 151731066a59e10ddc7bb6c95d0b91b3e0e11e10396Craig Stout mSearchOrbView.setOnOrbClickedListener(listener); 152977f0610fcfc783a9ed91ccb08387472b743ce63Dake Gu updateSearchOrbViewVisiblity(); 153731066a59e10ddc7bb6c95d0b91b3e0e11e10396Craig Stout } 154731066a59e10ddc7bb6c95d0b91b3e0e11e10396Craig Stout 155731066a59e10ddc7bb6c95d0b91b3e0e11e10396Craig Stout /** 156731066a59e10ddc7bb6c95d0b91b3e0e11e10396Craig Stout * Returns the view for the search affordance. 157731066a59e10ddc7bb6c95d0b91b3e0e11e10396Craig Stout */ 158731066a59e10ddc7bb6c95d0b91b3e0e11e10396Craig Stout public View getSearchAffordanceView() { 159731066a59e10ddc7bb6c95d0b91b3e0e11e10396Craig Stout return mSearchOrbView; 160731066a59e10ddc7bb6c95d0b91b3e0e11e10396Craig Stout } 161731066a59e10ddc7bb6c95d0b91b3e0e11e10396Craig Stout 162731066a59e10ddc7bb6c95d0b91b3e0e11e10396Craig Stout /** 1634fdd3589c982860b831c0fad63c0082cb9079f47Craig Stout * Sets the {@link SearchOrbView.Colors} used to draw the search affordance. 164731066a59e10ddc7bb6c95d0b91b3e0e11e10396Craig Stout */ 1654fdd3589c982860b831c0fad63c0082cb9079f47Craig Stout public void setSearchAffordanceColors(SearchOrbView.Colors colors) { 1664fdd3589c982860b831c0fad63c0082cb9079f47Craig Stout mSearchOrbView.setOrbColors(colors); 167731066a59e10ddc7bb6c95d0b91b3e0e11e10396Craig Stout } 168731066a59e10ddc7bb6c95d0b91b3e0e11e10396Craig Stout 169731066a59e10ddc7bb6c95d0b91b3e0e11e10396Craig Stout /** 1704fdd3589c982860b831c0fad63c0082cb9079f47Craig Stout * Returns the {@link SearchOrbView.Colors} used to draw the search affordance. 171731066a59e10ddc7bb6c95d0b91b3e0e11e10396Craig Stout */ 1724fdd3589c982860b831c0fad63c0082cb9079f47Craig Stout public SearchOrbView.Colors getSearchAffordanceColors() { 1734fdd3589c982860b831c0fad63c0082cb9079f47Craig Stout return mSearchOrbView.getOrbColors(); 174731066a59e10ddc7bb6c95d0b91b3e0e11e10396Craig Stout } 175447860fd5c105dd0ccd227237ac5f18fdc4c26dcCraig Stout 176447860fd5c105dd0ccd227237ac5f18fdc4c26dcCraig Stout /** 177447860fd5c105dd0ccd227237ac5f18fdc4c26dcCraig Stout * Enables or disables any view animations. 178447860fd5c105dd0ccd227237ac5f18fdc4c26dcCraig Stout */ 179447860fd5c105dd0ccd227237ac5f18fdc4c26dcCraig Stout public void enableAnimation(boolean enable) { 180447860fd5c105dd0ccd227237ac5f18fdc4c26dcCraig Stout mSearchOrbView.enableOrbColorAnimation(enable && mSearchOrbView.hasFocus()); 181447860fd5c105dd0ccd227237ac5f18fdc4c26dcCraig Stout } 1827350fc450e5850b7a3dddff6d63fb87bd24886ddsusnata 1837350fc450e5850b7a3dddff6d63fb87bd24886ddsusnata /** 1847350fc450e5850b7a3dddff6d63fb87bd24886ddsusnata * Based on the flag, it updates the visibility of the individual components - 1857350fc450e5850b7a3dddff6d63fb87bd24886ddsusnata * BadgeView, TextView and SearchView. 1867350fc450e5850b7a3dddff6d63fb87bd24886ddsusnata * 1877350fc450e5850b7a3dddff6d63fb87bd24886ddsusnata * @param flags integer representing the visibility of TitleView components. 188a373804d10f93a9488adc35cf6ce44dce09b3778Dake Gu * @see TitleViewAdapter#SEARCH_VIEW_VISIBLE 189a373804d10f93a9488adc35cf6ce44dce09b3778Dake Gu * @see TitleViewAdapter#BRANDING_VIEW_VISIBLE 190a373804d10f93a9488adc35cf6ce44dce09b3778Dake Gu * @see TitleViewAdapter#FULL_VIEW_VISIBLE 1917350fc450e5850b7a3dddff6d63fb87bd24886ddsusnata */ 192a373804d10f93a9488adc35cf6ce44dce09b3778Dake Gu public void updateComponentsVisibility(int flags) { 1937350fc450e5850b7a3dddff6d63fb87bd24886ddsusnata this.flags = flags; 1947350fc450e5850b7a3dddff6d63fb87bd24886ddsusnata 1957350fc450e5850b7a3dddff6d63fb87bd24886ddsusnata if ((flags & BRANDING_VIEW_VISIBLE) == BRANDING_VIEW_VISIBLE) { 1967350fc450e5850b7a3dddff6d63fb87bd24886ddsusnata updateBadgeVisibility(); 1977350fc450e5850b7a3dddff6d63fb87bd24886ddsusnata } else { 1987350fc450e5850b7a3dddff6d63fb87bd24886ddsusnata mBadgeView.setVisibility(View.GONE); 1997350fc450e5850b7a3dddff6d63fb87bd24886ddsusnata mTextView.setVisibility(View.GONE); 2007350fc450e5850b7a3dddff6d63fb87bd24886ddsusnata } 201977f0610fcfc783a9ed91ccb08387472b743ce63Dake Gu updateSearchOrbViewVisiblity(); 202977f0610fcfc783a9ed91ccb08387472b743ce63Dake Gu } 2037350fc450e5850b7a3dddff6d63fb87bd24886ddsusnata 204977f0610fcfc783a9ed91ccb08387472b743ce63Dake Gu private void updateSearchOrbViewVisiblity() { 205977f0610fcfc783a9ed91ccb08387472b743ce63Dake Gu int visibility = mHasSearchListener && (flags & SEARCH_VIEW_VISIBLE) == SEARCH_VIEW_VISIBLE 2067350fc450e5850b7a3dddff6d63fb87bd24886ddsusnata ? View.VISIBLE : View.INVISIBLE; 2077350fc450e5850b7a3dddff6d63fb87bd24886ddsusnata mSearchOrbView.setVisibility(visibility); 2087350fc450e5850b7a3dddff6d63fb87bd24886ddsusnata } 2097350fc450e5850b7a3dddff6d63fb87bd24886ddsusnata 2107350fc450e5850b7a3dddff6d63fb87bd24886ddsusnata private void updateBadgeVisibility() { 2117350fc450e5850b7a3dddff6d63fb87bd24886ddsusnata Drawable drawable = mBadgeView.getDrawable(); 2127350fc450e5850b7a3dddff6d63fb87bd24886ddsusnata if (drawable != null) { 2137350fc450e5850b7a3dddff6d63fb87bd24886ddsusnata mBadgeView.setVisibility(View.VISIBLE); 2147350fc450e5850b7a3dddff6d63fb87bd24886ddsusnata mTextView.setVisibility(View.GONE); 2157350fc450e5850b7a3dddff6d63fb87bd24886ddsusnata } else { 2167350fc450e5850b7a3dddff6d63fb87bd24886ddsusnata mBadgeView.setVisibility(View.GONE); 2177350fc450e5850b7a3dddff6d63fb87bd24886ddsusnata mTextView.setVisibility(View.VISIBLE); 2187350fc450e5850b7a3dddff6d63fb87bd24886ddsusnata } 2197350fc450e5850b7a3dddff6d63fb87bd24886ddsusnata } 220a373804d10f93a9488adc35cf6ce44dce09b3778Dake Gu 221a373804d10f93a9488adc35cf6ce44dce09b3778Dake Gu @Override 222a373804d10f93a9488adc35cf6ce44dce09b3778Dake Gu public TitleViewAdapter getTitleViewAdapter() { 223a373804d10f93a9488adc35cf6ce44dce09b3778Dake Gu return mTitleViewAdapter; 224a373804d10f93a9488adc35cf6ce44dce09b3778Dake Gu } 225731066a59e10ddc7bb6c95d0b91b3e0e11e10396Craig Stout} 226