@Override
 public Object instantiateItem(View container, int position) {
   synchronized (viewsLock) {
     ViewGroup pager = (ViewGroup) container;
     TiViewProxy tiProxy = mViews.get(position);
     TiUIView tiView = tiProxy.getOrCreateView();
     View view = tiView.getOuterView();
     ViewGroup.LayoutParams params =
         new ViewGroup.LayoutParams(LayoutParams.MATCH_PARENT, LayoutParams.MATCH_PARENT);
     TiCompositeLayout layout = new TiCompositeLayout(tiProxy.getActivity());
     ViewParent parent = view.getParent();
     if (parent instanceof ViewGroup) {
       pager.removeView((View) parent);
       ViewGroup group = (ViewGroup) parent;
       group.removeView(view);
     }
     layout.addView(view, tiView.getLayoutParams());
     if (position < pager.getChildCount()) {
       pager.addView(layout, position, params);
     } else {
       pager.addView(layout, params);
     }
     return tiProxy;
   }
 }
  public TiUIScrollableView(ScrollableViewProxy proxy, TiBaseActivity activity) {
    super(proxy);
    //		activity.addConfigurationChangedListener(this);

    mViews = new ArrayList<TiViewProxy>();
    viewsLock = new Object();
    buildViewPager(activity);
    TiCompositeLayout.LayoutParams params = new LayoutParams();
    params.optionWidth = new TiDimension("100%", TiDimension.TYPE_WIDTH);
    params.optionHeight = new TiDimension("100%", TiDimension.TYPE_HEIGHT);
    mPager.setLayoutParams(params);
    mContainer =
        new TiViewPagerLayout(activity) {
          @Override
          public boolean dispatchTouchEvent(MotionEvent event) {
            if (touchPassThrough == true) return false;
            return super.dispatchTouchEvent(event);
          }
        };
    mContainer.addView((View) mPager, params);
    mPagingControl = buildPagingControl(activity);
    mContainer.addView(mPagingControl, buildFillLayoutParams());

    setNativeView(mContainer);
  }
예제 #3
0
  public TiUIFragment(TiViewProxy proxy, Activity activity) {
    super(proxy);
    // When 'fragmentOnly' property is enabled, we generate the standalone fragment, enabling
    // us to add it directly to other fragment managers.
    if (proxy.hasProperty(TiC.PROPERTY_FRAGMENT_ONLY)) {
      fragmentOnly = TiConvert.toBoolean(proxy.getProperty(TiC.PROPERTY_FRAGMENT_ONLY), false);
    }

    if (fragmentOnly) {
      fragment = createFragment();
    } else {
      TiCompositeLayout container =
          new TiCompositeLayout(activity, proxy) {
            @Override
            public boolean dispatchTouchEvent(MotionEvent ev) {
              return interceptTouchEvent(ev) || super.dispatchTouchEvent(ev);
            }
          };
      container.setId(viewId++);
      setNativeView(container);

      FragmentManager manager = ((FragmentActivity) activity).getSupportFragmentManager();
      FragmentTransaction transaction = manager.beginTransaction();
      fragment = createFragment();
      transaction.add(container.getId(), fragment);
      transaction.commitAllowingStateLoss();
    }
  }
예제 #4
0
 public View layoutHeaderOrFooterView(TiViewProxy viewProxy) {
   TiUIView tiView = viewProxy.peekView();
   if (tiView != null) {
     TiViewProxy parentProxy = viewProxy.getParent();
     // Remove parent view if possible
     if (parentProxy != null) {
       TiUIView parentView = parentProxy.peekView();
       if (parentView != null) {
         parentView.remove(tiView);
       }
     }
   } else {
     tiView = viewProxy.forceCreateView();
   }
   View outerView = tiView.getOuterView();
   ViewGroup parentView = (ViewGroup) outerView.getParent();
   if (parentView != null && parentView.getId() == HEADER_FOOTER_WRAP_ID) {
     return parentView;
   } else {
     // add a wrapper so layout params such as height, width takes in effect.
     TiCompositeLayout wrapper =
         new TiCompositeLayout(viewProxy.getActivity(), LayoutArrangement.DEFAULT, null);
     AbsListView.LayoutParams params =
         new AbsListView.LayoutParams(
             AbsListView.LayoutParams.MATCH_PARENT, AbsListView.LayoutParams.WRAP_CONTENT);
     wrapper.setLayoutParams(params);
     outerView = tiView.getOuterView();
     wrapper.addView(outerView, tiView.getLayoutParams());
     wrapper.setId(HEADER_FOOTER_WRAP_ID);
     return wrapper;
   }
 }
 @Override
 public boolean isViewFromObject(View view, Object object) {
   synchronized (viewsLock) {
     TiViewProxy tiProxy = (TiViewProxy) object;
     if (tiProxy != null) {
       View outerView = tiProxy.getOuterView();
       if (outerView != null) {
         TiCompositeLayout layout = (TiCompositeLayout) outerView.getParent();
         return (layout != null && layout.equals(view));
       }
     }
   }
   return false;
 }
  public void showPager() {
    View v = null;
    v = mContainer.findViewById(PAGE_LEFT);
    if (v != null) {
      v.setVisibility(mCurIndex > 0 ? View.VISIBLE : View.INVISIBLE);
    }

    v = mContainer.findViewById(PAGE_RIGHT);
    if (v != null) {
      v.setVisibility(mCurIndex < (mViews.size() - 1) ? View.VISIBLE : View.INVISIBLE);
    }

    mPagingControl.setVisibility(View.VISIBLE);
    ((ScrollableViewProxy) proxy).setPagerTimeout();
  }
 @Override
 protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
   super.onMeasure(widthMeasureSpec, heightMeasureSpec);
   setMeasuredDimension(
       Math.max(measuredWidth, getMeasuredWidth()),
       Math.max(measuredHeight, getMeasuredHeight()));
 }
예제 #8
0
 @Override
 protected void dispatchDraw(Canvas canvas) {
   super.dispatchDraw(canvas);
   if (enabled) {
     drawMask(canvas);
   }
 }
  protected void refreshControls() {
    ArrayList<TiViewProxy> proxies = getRowProxy().getControls();
    int len = proxies.size();

    if (views == null) {
      views = new ArrayList<TiUIView>(len);
    } else if (views.size() != len) {
      for (TiUIView view : views) {
        View v = view.getNativeView();
        if (v != null && v.getParent().equals(content)) {
          content.removeView(v);
        }
      }
      views = new ArrayList<TiUIView>(len);
    }

    for (int i = 0; i < len; i++) {
      TiUIView view = views.size() > i ? views.get(i) : null;
      TiViewProxy proxy = proxies.get(i);
      if (view != null && view.getProxy() instanceof TableViewRowProxy) {
        proxy = addViewToOldRow(i, view, proxy);
        len++;
      }
      if (view == null) {
        // In some cases the TiUIView for this proxy has been reassigned to another proxy
        // We don't want to actually release it though, just reassign by creating a new view
        view = proxy.forceCreateView(tiContext.getActivity());
        clearChildViews(proxy);
        if (i >= views.size()) {
          views.add(view);
        } else {
          views.set(i, view);
        }
      }

      View v = view.getNativeView();
      view.setProxy(proxy);
      view.processProperties(proxy.getProperties());
      applyChildProxies(proxy, view);
      if (v != null && v.getParent() == null) {
        content.addView(v, view.getLayoutParams());
      }
    }
  }
예제 #10
0
  public void processProperties(KrollDict d) {
    if (d.containsKey(TiC.PROPERTY_LAYOUT)) {
      String layout = TiConvert.toString(d, TiC.PROPERTY_LAYOUT);
      if (nativeView instanceof TiCompositeLayout) {
        ((TiCompositeLayout) nativeView).setLayoutArrangement(layout);
      }
    }
    if (TiConvert.fillLayout(d, layoutParams)) {
      if (nativeView != null) {
        nativeView.requestLayout();
      }
    }

    Integer bgColor = null;

    // Default background processing.
    // Prefer image to color.
    if (hasImage(d) || hasColorState(d) || hasBorder(d)) {
      handleBackgroundImage(d);
    } else if (d.containsKey(TiC.PROPERTY_BACKGROUND_COLOR)) {
      bgColor = TiConvert.toColor(d, TiC.PROPERTY_BACKGROUND_COLOR);
      nativeView.setBackgroundColor(bgColor);
    }
    if (d.containsKey(TiC.PROPERTY_OPACITY)) {
      if (nativeView != null) {
        setOpacity(TiConvert.toFloat(d, TiC.PROPERTY_OPACITY));
      }
    }

    if (d.containsKey(TiC.PROPERTY_VISIBLE)) {
      nativeView.setVisibility(
          TiConvert.toBoolean(d, TiC.PROPERTY_VISIBLE) ? View.VISIBLE : View.INVISIBLE);
    }
    if (d.containsKey(TiC.PROPERTY_ENABLED)) {
      nativeView.setEnabled(TiConvert.toBoolean(d, TiC.PROPERTY_ENABLED));
    }

    if (d.containsKey(TiC.PROPERTY_FOCUSABLE)) {
      boolean focusable = TiConvert.toBoolean(d, TiC.PROPERTY_FOCUSABLE);
      nativeView.setFocusable(focusable);
      if (focusable) {
        registerForKeyClick(nativeView);
      } else {
        nativeView.setOnClickListener(null);
      }
    }

    initializeBorder(d, bgColor);

    if (d.containsKey(TiC.PROPERTY_TRANSFORM)) {
      Ti2DMatrix matrix = (Ti2DMatrix) d.get(TiC.PROPERTY_TRANSFORM);
      if (matrix != null) {
        applyTransform(matrix);
      }
    }
  }
예제 #11
0
 // Animation
 @Override
 public void invalidateDrawable(Drawable dr) {
   if (dr != getBackground() && dr != null) {
     initMask(dr);
     swapBitmapMask(makeBitmapMask(dr));
     invalidate();
   } else {
     super.invalidateDrawable(dr);
   }
 }
    @Override
    protected void constrainChild(View child, int width, int wMode, int height, int hMode) {

      super.constrainChild(child, width, wMode, height, hMode);

      // We need to support an automatically growing contentArea, so this code is
      // updates the measured dimensions as needed. absWidth, absHeight are
      // left in for debugging purposes. ATM

      int absWidth = calculateAbsoluteRight(child);
      int absHeight = calculateAbsoluteBottom(child);
    }
  public TiTableViewRowProxyItem(TiContext tiContext) {
    super(tiContext);

    this.handler = new Handler(this);
    this.leftImage = new ImageView(tiContext.getActivity());
    leftImage.setVisibility(GONE);
    addView(leftImage, new LayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT));

    this.content = new TiCompositeLayout(tiContext.getActivity());
    content.setMinimumHeight(48);
    addView(content, new LayoutParams(LayoutParams.FILL_PARENT, LayoutParams.FILL_PARENT));

    this.rightImage = new ImageView(tiContext.getActivity());
    rightImage.setVisibility(GONE);
    addView(rightImage, new LayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT));
  }
예제 #14
0
 protected void layoutNativeView(boolean informParent) {
   if (nativeView != null) {
     Animation a = nativeView.getAnimation();
     if (a != null && a instanceof TiMatrixAnimation) {
       TiMatrixAnimation matrixAnimation = (TiMatrixAnimation) a;
       matrixAnimation.invalidateWithMatrix(nativeView);
     }
     if (informParent) {
       if (parent != null) {
         TiUIView uiv = parent.peekView();
         if (uiv != null) {
           View v = uiv.getNativeView();
           if (v instanceof TiCompositeLayout) {
             ((TiCompositeLayout) v).resort();
           }
         }
       }
     }
     nativeView.requestLayout();
   }
 }
 protected void refreshOldStyleRow() {
   TableViewRowProxy rp = getRowProxy();
   if (!rp.hasProperty(TiC.PROPERTY_TOUCH_ENABLED)) {
     rp.setProperty(TiC.PROPERTY_TOUCH_ENABLED, false);
   }
   if (views == null) {
     views = new ArrayList<TiUIView>();
     views.add(new TiUILabel(rp));
   }
   TiUILabel t = (TiUILabel) views.get(0);
   t.setProxy(rp);
   t.processProperties(filterProperties(rp.getProperties()));
   View v = t.getNativeView();
   if (v.getParent() == null) {
     TiCompositeLayout.LayoutParams params = (TiCompositeLayout.LayoutParams) t.getLayoutParams();
     params.optionLeft = new TiDimension(5, TiDimension.TYPE_LEFT);
     params.optionRight = new TiDimension(5, TiDimension.TYPE_RIGHT);
     params.autoFillsWidth = true;
     content.addView(v, params);
   }
 }
 @Override
 public void release() {
   super.release();
   if (views != null) {
     for (TiUIView view : views) {
       view.release();
     }
     views = null;
   }
   if (content != null) {
     content.removeAllViews();
     content = null;
   }
   if (hasCheckDrawable != null) {
     hasCheckDrawable.setCallback(null);
     hasCheckDrawable = null;
   }
   if (hasChildDrawable != null) {
     hasChildDrawable.setCallback(null);
     hasChildDrawable = null;
   }
 }
  @Override
  protected void onLayout(boolean changed, int left, int top, int right, int bottom) {
    int contentLeft = left;
    int contentRight = right;
    bottom = bottom - top;
    top = 0;

    int height = bottom - top;

    if (leftImage != null && leftImage.getVisibility() != GONE) {
      int w = leftImage.getMeasuredWidth();
      int h = leftImage.getMeasuredHeight();
      int leftMargin = LEFT_MARGIN;

      contentLeft += w + leftMargin;
      int offset = (height - h) / 2;
      leftImage.layout(left + leftMargin, top + offset, left + leftMargin + w, top + offset + h);
    }

    if (rightImage != null && rightImage.getVisibility() != GONE) {
      int w = rightImage.getMeasuredWidth();
      int h = rightImage.getMeasuredHeight();
      int rightMargin = RIGHT_MARGIN;

      contentRight -= w + rightMargin;
      int offset = (height - h) / 2;
      rightImage.layout(
          right - w - rightMargin, top + offset, right - rightMargin, top + offset + h);
    }

    if (hasControls) {
      contentLeft = left + LEFT_MARGIN;
      contentRight = right - RIGHT_MARGIN;
    }

    if (content != null) {
      content.layout(contentLeft, top, contentRight, bottom);
    }
  }
예제 #18
0
  @Override
  protected void onDestroy() {
    super.onDestroy();
    for (WeakReference<TiContext> contextRef : contexts) {
      TiContext ctx = contextRef.get();
      if (ctx != null) {
        ctx.dispatchOnDestroy();
        ctx.release();
      }
    }
    if (layout != null) {
      Log.e(LCAT, "Layout cleanup.");
      layout.removeAllViews();
      layout = null;
    }

    if (proxy != null) {
      proxy.closeFromActivity();
      proxy = null;
    }

    handler = null;
  }
예제 #19
0
 @Override
 public void addWindow(View v, TiCompositeLayout.LayoutParams params) {
   layout.addView(v, params);
 }
예제 #20
0
 @Override
 protected void onLayout(boolean changed, int l, int t, int r, int b) {
   super.onLayout(changed, l, t, r, b);
   updateSize(getMeasuredWidth(), getMeasuredHeight());
 }
예제 #21
0
 // Once the size has changed we need to remake the mask.
 @Override
 protected void onSizeChanged(int w, int h, int oldw, int oldh) {
   super.onSizeChanged(w, h, oldw, oldh);
   updateSize(w, h);
 }
예제 #22
0
 /**
  * Sets the proxy for our layout (used for post layout event)
  *
  * @param proxy
  */
 public void setLayoutProxy(TiViewProxy proxy) {
   if (layout instanceof TiCompositeLayout) {
     ((TiCompositeLayout) layout).setProxy(proxy);
   }
 }
예제 #23
0
  @Override
  /**
   * When this activity is destroyed, this method removes it from the activity stack, performs clean
   * up, and fires javascript 'destroy' event.
   */
  protected void onDestroy() {
    Log.d(TAG, "Activity " + this + " onDestroy", Log.DEBUG_MODE);

    inForeground = false;
    TiApplication tiApp = getTiApp();
    // Clean up dialogs when activity is destroyed.
    releaseDialogs(true);

    if (tiApp.isRestartPending()) {
      super.onDestroy();
      if (!isFinishing()) {
        finish();
      }
      return;
    }

    synchronized (lifecycleListeners.synchronizedList()) {
      for (OnLifecycleEvent listener : lifecycleListeners.nonNull()) {
        try {
          TiLifecycle.fireLifecycleEvent(this, listener, TiLifecycle.LIFECYCLE_ON_DESTROY);

        } catch (Throwable t) {
          Log.e(TAG, "Error dispatching lifecycle event: " + t.getMessage(), t);
        }
      }
    }

    super.onDestroy();

    boolean isFinishing = isFinishing();

    // If the activity is finishing, remove the windowId and supportHelperId so the window and
    // supportHelper can be released.
    // If the activity is forced to destroy by Android OS, keep the windowId and supportHelperId so
    // the activity can be recovered.
    if (isFinishing) {
      int windowId = getIntentInt(TiC.INTENT_PROPERTY_WINDOW_ID, -1);
      TiActivityWindows.removeWindow(windowId);
      TiActivitySupportHelpers.removeSupportHelper(supportHelperId);
    }

    fireOnDestroy();

    if (layout instanceof TiCompositeLayout) {
      Log.e(TAG, "Layout cleanup.", Log.DEBUG_MODE);
      ((TiCompositeLayout) layout).removeAllViews();
    }
    layout = null;

    // LW windows
    if (window == null && view != null) {
      view.releaseViews();
      view = null;
    }

    if (window != null) {
      window.closeFromActivity(isFinishing);
      window = null;
    }

    if (menuHelper != null) {
      menuHelper.destroy();
      menuHelper = null;
    }

    if (activityProxy != null) {
      activityProxy.release();
      activityProxy = null;
    }

    // Don't dispose the runtime if the activity is forced to destroy by Android,
    // so we can recover the activity later.
    KrollRuntime.decrementActivityRefCount(isFinishing);
    KrollRuntime.suggestGC();
  }
예제 #24
0
 @Override
 public void removeWindow(View v) {
   layout.removeView(v);
 }
 @Override
 protected void onLayout(boolean changed, int l, int t, int r, int b) {
   super.onLayout(changed, l, t, r, b);
   measuredHeight = measuredWidth = 0;
 }
  public void setRowData(TableViewRowProxy rp) {
    KrollDict props = rp.getProperties();
    hasControls = rp.hasControls();

    Object newSelectorSource = null;
    if (rp.hasProperty(TiC.PROPERTY_BACKGROUND_SELECTED_IMAGE)) {
      newSelectorSource = rp.getProperty(TiC.PROPERTY_BACKGROUND_SELECTED_IMAGE);
    } else if (rp.hasProperty(TiC.PROPERTY_BACKGROUND_SELECTED_COLOR)) {
      newSelectorSource = rp.getProperty(TiC.PROPERTY_BACKGROUND_SELECTED_COLOR);
    }
    if (newSelectorSource == null
        || selectorSource != null && !selectorSource.equals(newSelectorSource)) {
      selectorDrawable = null;
    }
    selectorSource = newSelectorSource;
    if (selectorSource != null) {
      rp.getTable().getTableView().getTableView().enableCustomSelector();
    }

    setBackgroundFromProperties(props);
    // Handle right image
    boolean clearRightImage = true;
    // It's one or the other, check or child.  If you set them both, child's gonna win.
    if (props.containsKey(TiC.PROPERTY_HAS_CHECK)) {
      if (TiConvert.toBoolean(props, TiC.PROPERTY_HAS_CHECK)) {
        if (hasCheckDrawable == null) {
          hasCheckDrawable = createHasCheckDrawable();
        }
        rightImage.setImageDrawable(hasCheckDrawable);
        rightImage.setVisibility(VISIBLE);
        clearRightImage = false;
      }
    }
    if (props.containsKey(TiC.PROPERTY_HAS_CHILD)) {
      if (TiConvert.toBoolean(props, TiC.PROPERTY_HAS_CHILD)) {
        if (hasChildDrawable == null) {
          hasChildDrawable = createHasChildDrawable();
        }
        rightImage.setImageDrawable(hasChildDrawable);
        rightImage.setVisibility(VISIBLE);
        clearRightImage = false;
      }
    }
    if (props.containsKey(TiC.PROPERTY_RIGHT_IMAGE)) {
      String path = TiConvert.toString(props, TiC.PROPERTY_RIGHT_IMAGE);
      String url = tiContext.resolveUrl(null, path);
      Drawable d = loadDrawable(url);
      if (d != null) {
        rightImage.setImageDrawable(d);
        rightImage.setVisibility(VISIBLE);
        clearRightImage = false;
      }
    }

    if (clearRightImage) {
      rightImage.setImageDrawable(null);
      rightImage.setVisibility(GONE);
    }

    // Handle left image
    if (props.containsKey(TiC.PROPERTY_LEFT_IMAGE)) {
      String path = TiConvert.toString(props, TiC.PROPERTY_LEFT_IMAGE);
      String url = tiContext.resolveUrl(null, path);

      Drawable d = loadDrawable(url);
      if (d != null) {
        leftImage.setImageDrawable(d);
        leftImage.setVisibility(VISIBLE);
      }
    } else {
      leftImage.setImageDrawable(null);
      leftImage.setVisibility(GONE);
    }

    if (props.containsKey(TiC.PROPERTY_HEIGHT)) {
      if (!props.get(TiC.PROPERTY_HEIGHT).equals(TiC.SIZE_AUTO)) {
        height =
            TiConvert.toTiDimension(
                TiConvert.toString(props, TiC.PROPERTY_HEIGHT), TiDimension.TYPE_HEIGHT);
      }
    }

    if (props.containsKey(TiC.PROPERTY_LAYOUT)) {
      content.setLayoutArrangement(TiConvert.toString(props, TiC.PROPERTY_LAYOUT));
    }

    if (rp.hasControls()) {
      refreshControls();
    } else {
      refreshOldStyleRow();
    }
  }
  @Override
  protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
    int w = MeasureSpec.getSize(widthMeasureSpec);
    int wMode = MeasureSpec.getMode(widthMeasureSpec);
    int h = MeasureSpec.getSize(heightMeasureSpec);
    int hMode = MeasureSpec.getMode(heightMeasureSpec);
    int imageHMargin = 0;

    int leftImageWidth = 0;
    int leftImageHeight = 0;
    if (leftImage != null && leftImage.getVisibility() != View.GONE) {
      measureChild(leftImage, widthMeasureSpec, heightMeasureSpec);
      leftImageWidth = leftImage.getMeasuredWidth();
      leftImageHeight = leftImage.getMeasuredHeight();
      imageHMargin += LEFT_MARGIN;
    }

    int rightImageWidth = 0;
    int rightImageHeight = 0;
    if (rightImage != null && rightImage.getVisibility() != View.GONE) {
      measureChild(rightImage, widthMeasureSpec, heightMeasureSpec);
      rightImageWidth = rightImage.getMeasuredWidth();
      rightImageHeight = rightImage.getMeasuredHeight();
      imageHMargin += RIGHT_MARGIN;
    }

    int adjustedWidth = w - leftImageWidth - rightImageWidth - imageHMargin;
    // int adjustedWidth = w;

    if (content != null) {
      measureChild(content, MeasureSpec.makeMeasureSpec(adjustedWidth, wMode), heightMeasureSpec);
      if (hMode == MeasureSpec.UNSPECIFIED) {
        TableViewProxy table = ((TableViewRowProxy) item.proxy).getTable();
        int minRowHeight = -1;
        if (table != null && table.hasProperty(TiC.PROPERTY_MIN_ROW_HEIGHT)) {
          minRowHeight =
              TiConvert.toTiDimension(
                      TiConvert.toString(table.getProperty(TiC.PROPERTY_MIN_ROW_HEIGHT)),
                      TiDimension.TYPE_HEIGHT)
                  .getAsPixels(this);
        }

        if (height == null) {
          h =
              Math.max(
                  h,
                  Math.max(
                      content.getMeasuredHeight(), Math.max(leftImageHeight, rightImageHeight)));
          h = Math.max(h, minRowHeight);
        } else {
          h = Math.max(minRowHeight, height.getAsPixels(this));
        }
        if (DBG) {
          Log.d(LCAT, "Row content measure (" + adjustedWidth + "x" + h + ")");
        }
        measureChild(
            content,
            MeasureSpec.makeMeasureSpec(adjustedWidth, wMode),
            MeasureSpec.makeMeasureSpec(h, hMode));
      }
    }

    setMeasuredDimension(w, Math.max(h, Math.max(leftImageHeight, rightImageHeight)));
  }