1ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi/* 2ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi * Copyright (C) 2010 The Android Open Source Project 3ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi * 4ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi * Licensed under the Apache License, Version 2.0 (the "License"); 5ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi * you may not use this file except in compliance with the License. 6ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi * You may obtain a copy of the License at 7ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi * 8ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi * http://www.apache.org/licenses/LICENSE-2.0 9ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi * 10ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi * Unless required by applicable law or agreed to in writing, software 11ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi * distributed under the License is distributed on an "AS IS" BASIS, 12ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi * See the License for the specific language governing permissions and 14ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi * limitations under the License. 15ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi */ 16ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi 1781393d6dc5767f7784a00958095614a37bf1a91aGil Dobjanschipackage com.android.videoeditor.widgets; 18ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi 1981393d6dc5767f7784a00958095614a37bf1a91aGil Dobjanschiimport com.android.videoeditor.R; 20ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi 21ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschiimport android.content.Context; 22ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschiimport android.content.res.Resources; 23ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschiimport android.graphics.Canvas; 24ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschiimport android.graphics.drawable.Drawable; 25ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschiimport android.util.AttributeSet; 26ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschiimport android.view.MotionEvent; 27ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschiimport android.widget.ImageView; 28ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi 29ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi/** 30ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi * The view that represents a resize handle 31ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi */ 32ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschipublic class HandleView extends ImageView { 33ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi // Instance variables 340a566814a035781c4aecb0d5019a813fe0b1939bShih-chia Cheng private final Drawable mIconDragClipLeft; 350a566814a035781c4aecb0d5019a813fe0b1939bShih-chia Cheng private final Drawable mIconDragClipRight; 36ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi private MoveListener mListener; 37c509d6b57b3dba1d24dd4e68b315f2e565ae47a5Gil Dobjanschi private float mStartMoveX, mLastMoveX; 38ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi private boolean mMoveStarted; 39ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi private boolean mBeginLimitReached, mEndLimitReached; 40590396edcdcc30e4770d19b8903f81150eab71cbGil Dobjanschi private int mLastDeltaX; 41ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi 42ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi /** 43ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi * Move listener 44ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi */ 45ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi public interface MoveListener { 46ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi /** 47ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi * The move begins 48ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi * 49ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi * @param view The view 50ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi */ 51ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi public void onMoveBegin(HandleView view); 52ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi 53ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi /** 54ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi * Move is in progress 55ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi * 56ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi * @param view The view 57590396edcdcc30e4770d19b8903f81150eab71cbGil Dobjanschi * @param left The left edge left position 58590396edcdcc30e4770d19b8903f81150eab71cbGil Dobjanschi * @param delta The offset relative to the left of the view 59ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi */ 60590396edcdcc30e4770d19b8903f81150eab71cbGil Dobjanschi public boolean onMove(HandleView view, int left, int delta); 61ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi 62ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi /** 63ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi * The move ended 64ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi * 65ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi * @param view The view 66590396edcdcc30e4770d19b8903f81150eab71cbGil Dobjanschi * @param left The left edge left position 67590396edcdcc30e4770d19b8903f81150eab71cbGil Dobjanschi * @param delta The offset relative to the left of the view 68ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi */ 69590396edcdcc30e4770d19b8903f81150eab71cbGil Dobjanschi public void onMoveEnd(HandleView view, int left, int delta); 70ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi } 71ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi 72ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi public HandleView(Context context, AttributeSet attrs, int defStyle) { 73ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi super(context, attrs, defStyle); 74ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi 75ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi // Prepare the handle arrows 76ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi final Resources resources = getResources(); 770a566814a035781c4aecb0d5019a813fe0b1939bShih-chia Cheng mIconDragClipLeft = resources.getDrawable(R.drawable.ic_drag_clip_left); 780a566814a035781c4aecb0d5019a813fe0b1939bShih-chia Cheng mIconDragClipRight = resources.getDrawable(R.drawable.ic_drag_clip_right); 79ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi } 80ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi 81ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi public HandleView(Context context, AttributeSet attrs) { 82ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi this(context, attrs, 0); 83ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi } 84ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi 85ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi public HandleView(Context context) { 86ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi this(context, null, 0); 87ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi } 88ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi 89ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi /** 90ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi * @param listener The listener 91ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi */ 92ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi public void setListener(MoveListener listener) { 93ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi mListener = listener; 94ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi } 95ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi 96ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi /** 97ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi * Set the movement limits 98ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi * 99ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi * @param beginLimitReached true if the begin limit was reached 100ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi * @param endLimitReached true if the end limit was reached 101ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi */ 102ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi public void setLimitReached(boolean beginLimitReached, boolean endLimitReached) { 103ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi // Check if anything has changed 104ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi if (beginLimitReached == mBeginLimitReached && endLimitReached == mEndLimitReached) { 105ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi return; 106ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi } 107ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi 108ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi mBeginLimitReached = beginLimitReached; 109ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi mEndLimitReached = endLimitReached; 110ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi 111ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi invalidate(); 112ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi } 113ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi 114c509d6b57b3dba1d24dd4e68b315f2e565ae47a5Gil Dobjanschi /** 115c509d6b57b3dba1d24dd4e68b315f2e565ae47a5Gil Dobjanschi * End the move 116c509d6b57b3dba1d24dd4e68b315f2e565ae47a5Gil Dobjanschi */ 117c509d6b57b3dba1d24dd4e68b315f2e565ae47a5Gil Dobjanschi public void endMove() { 118c509d6b57b3dba1d24dd4e68b315f2e565ae47a5Gil Dobjanschi if (mMoveStarted) { 119c509d6b57b3dba1d24dd4e68b315f2e565ae47a5Gil Dobjanschi endActionMove(mLastMoveX); 120c509d6b57b3dba1d24dd4e68b315f2e565ae47a5Gil Dobjanschi } 121c509d6b57b3dba1d24dd4e68b315f2e565ae47a5Gil Dobjanschi } 122c509d6b57b3dba1d24dd4e68b315f2e565ae47a5Gil Dobjanschi 123ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi @Override 124ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi public boolean onTouchEvent(MotionEvent ev) { 125ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi super.onTouchEvent(ev); 126ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi 127ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi switch (ev.getAction()) { 128ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi case MotionEvent.ACTION_DOWN: { 129ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi if (isEnabled()) { 130ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi // The ScrollView will not get the touch events 131ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi getParent().requestDisallowInterceptTouchEvent(true); 132ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi if (mListener != null) { 133ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi mListener.onMoveBegin(this); 134ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi } 135ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi 136ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi mStartMoveX = ev.getX(); 137ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi mMoveStarted = true; 138ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi } else { 139ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi mMoveStarted = false; 140ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi } 141590396edcdcc30e4770d19b8903f81150eab71cbGil Dobjanschi 142590396edcdcc30e4770d19b8903f81150eab71cbGil Dobjanschi mLastDeltaX = -10000; 143ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi break; 144ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi } 145ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi 146ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi case MotionEvent.ACTION_MOVE: { 147ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi if (mMoveStarted && isEnabled()) { 148590396edcdcc30e4770d19b8903f81150eab71cbGil Dobjanschi final int deltaX = Math.round((ev.getX() - mStartMoveX)); 149590396edcdcc30e4770d19b8903f81150eab71cbGil Dobjanschi if (deltaX != mLastDeltaX) { 150590396edcdcc30e4770d19b8903f81150eab71cbGil Dobjanschi mLastDeltaX = deltaX; 151590396edcdcc30e4770d19b8903f81150eab71cbGil Dobjanschi 152590396edcdcc30e4770d19b8903f81150eab71cbGil Dobjanschi if (mListener != null) { 153590396edcdcc30e4770d19b8903f81150eab71cbGil Dobjanschi if (getId() == R.id.handle_left) { 154590396edcdcc30e4770d19b8903f81150eab71cbGil Dobjanschi mListener.onMove(this, getLeft(), deltaX + getWidth()); 155590396edcdcc30e4770d19b8903f81150eab71cbGil Dobjanschi } else { 156590396edcdcc30e4770d19b8903f81150eab71cbGil Dobjanschi mListener.onMove(this, getLeft(), deltaX); 157590396edcdcc30e4770d19b8903f81150eab71cbGil Dobjanschi } 158590396edcdcc30e4770d19b8903f81150eab71cbGil Dobjanschi } 159590396edcdcc30e4770d19b8903f81150eab71cbGil Dobjanschi 160590396edcdcc30e4770d19b8903f81150eab71cbGil Dobjanschi mLastMoveX = ev.getX(); 161ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi } 162ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi } 163ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi break; 164ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi } 165ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi 166ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi case MotionEvent.ACTION_CANCEL: 167ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi case MotionEvent.ACTION_UP: { 168c509d6b57b3dba1d24dd4e68b315f2e565ae47a5Gil Dobjanschi endActionMove(ev.getX()); 169ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi break; 170ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi } 171ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi 172ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi default: { 173ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi break; 174ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi } 175ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi } 176ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi 177ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi return true; 178ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi } 179ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi 180c509d6b57b3dba1d24dd4e68b315f2e565ae47a5Gil Dobjanschi /** 181c509d6b57b3dba1d24dd4e68b315f2e565ae47a5Gil Dobjanschi * End the move (if it was in progress) 182c509d6b57b3dba1d24dd4e68b315f2e565ae47a5Gil Dobjanschi * 183c509d6b57b3dba1d24dd4e68b315f2e565ae47a5Gil Dobjanschi * @param eventX The event horizontal position 184c509d6b57b3dba1d24dd4e68b315f2e565ae47a5Gil Dobjanschi */ 185c509d6b57b3dba1d24dd4e68b315f2e565ae47a5Gil Dobjanschi private void endActionMove(float eventX) { 186c509d6b57b3dba1d24dd4e68b315f2e565ae47a5Gil Dobjanschi if (mMoveStarted) { 187c509d6b57b3dba1d24dd4e68b315f2e565ae47a5Gil Dobjanschi mMoveStarted = false; 188590396edcdcc30e4770d19b8903f81150eab71cbGil Dobjanschi 1891b5e90e3748ca3ed3bfa5f2d49f18123d373ad0cGil Dobjanschi if (mListener != null) { 1901b5e90e3748ca3ed3bfa5f2d49f18123d373ad0cGil Dobjanschi final int deltaX = Math.round((eventX - mStartMoveX)); 1911b5e90e3748ca3ed3bfa5f2d49f18123d373ad0cGil Dobjanschi if (getId() == R.id.handle_left) { 1921b5e90e3748ca3ed3bfa5f2d49f18123d373ad0cGil Dobjanschi mListener.onMoveEnd(this, getLeft(), deltaX + getWidth()); 1931b5e90e3748ca3ed3bfa5f2d49f18123d373ad0cGil Dobjanschi } else { 1941b5e90e3748ca3ed3bfa5f2d49f18123d373ad0cGil Dobjanschi mListener.onMoveEnd(this, getLeft(), deltaX); 1951b5e90e3748ca3ed3bfa5f2d49f18123d373ad0cGil Dobjanschi } 196c509d6b57b3dba1d24dd4e68b315f2e565ae47a5Gil Dobjanschi } 197c509d6b57b3dba1d24dd4e68b315f2e565ae47a5Gil Dobjanschi } 198c509d6b57b3dba1d24dd4e68b315f2e565ae47a5Gil Dobjanschi } 199c509d6b57b3dba1d24dd4e68b315f2e565ae47a5Gil Dobjanschi 200ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi @Override 201ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi protected void onDraw(Canvas canvas) { 202ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi super.onDraw(canvas); 203ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi 2040a566814a035781c4aecb0d5019a813fe0b1939bShih-chia Cheng final int top = (getHeight() - mIconDragClipLeft.getIntrinsicHeight()) / 2; 205ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi if (!mBeginLimitReached) { 2060a566814a035781c4aecb0d5019a813fe0b1939bShih-chia Cheng mIconDragClipLeft.setBounds(0, 2070a566814a035781c4aecb0d5019a813fe0b1939bShih-chia Cheng top, 2080a566814a035781c4aecb0d5019a813fe0b1939bShih-chia Cheng mIconDragClipLeft.getIntrinsicWidth(), 2090a566814a035781c4aecb0d5019a813fe0b1939bShih-chia Cheng top + mIconDragClipLeft.getIntrinsicHeight()); 2100a566814a035781c4aecb0d5019a813fe0b1939bShih-chia Cheng mIconDragClipLeft.draw(canvas); 211ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi } 212ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi 213ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi if (!mEndLimitReached) { 2140a566814a035781c4aecb0d5019a813fe0b1939bShih-chia Cheng mIconDragClipRight.setBounds( 2150a566814a035781c4aecb0d5019a813fe0b1939bShih-chia Cheng mIconDragClipRight.getIntrinsicWidth(), 2160a566814a035781c4aecb0d5019a813fe0b1939bShih-chia Cheng top, 2170a566814a035781c4aecb0d5019a813fe0b1939bShih-chia Cheng 2 * mIconDragClipRight.getIntrinsicWidth(), 2180a566814a035781c4aecb0d5019a813fe0b1939bShih-chia Cheng top + mIconDragClipRight.getIntrinsicHeight()); 2190a566814a035781c4aecb0d5019a813fe0b1939bShih-chia Cheng mIconDragClipRight.draw(canvas); 220ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi } 221ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi } 222ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi} 223