@Override
    public boolean onTouchEvent(MotionEvent event) {
      if (event.getAction() != MotionEvent.ACTION_DOWN) return true;
      float x = event.getX();
      float y = event.getY();

      // If the touch event is located in the hue bar
      if (x > 10 && x < 266 && y > 0 && y < 40) {
        // Update the main field colors
        mCurrentHue = (255 - x) * 360 / 255;
        updateMainColors();

        // Update the current selected color
        int transX = mCurrentX - 10;
        int transY = mCurrentY - 60;
        int index = 256 * (transY - 1) + transX;
        if (index > 0 && index < mMainColors.length)
          mCurrentColor = mMainColors[256 * (transY - 1) + transX];

        // Force the redraw of the dialog
        invalidate();
      }

      // If the touch event is located in the main field
      if (x > 10 && x < 266 && y > 50 && y < 306) {
        mCurrentX = (int) x;
        mCurrentY = (int) y;
        int transX = mCurrentX - 10;
        int transY = mCurrentY - 60;
        int index = 256 * (transY - 1) + transX;
        if (index > 0 && index < mMainColors.length) {
          // Update the current color
          mCurrentColor = mMainColors[index];
          // Force the redraw of the dialog
          invalidate();
        }
      }

      // If the touch event is located in the left button, notify the listener with the current
      // color
      if (x > 10 && x < 138 && y > 316 && y < 356) mListener.colorChanged("", mCurrentColor);

      // If the touch event is located in the right button, notify the listener with the default
      // color
      if (x > 138 && x < 266 && y > 316 && y < 356) mListener.colorChanged("", mDefaultColor);

      return true;
    }
    @Override
    public boolean onTouchEvent(MotionEvent event) {
      float x = event.getX() - CENTER_X;
      float y = event.getY() - CENTER_Y;
      boolean inCenter = Math.sqrt(x * x + y * y) <= CENTER_RADIUS;

      switch (event.getAction()) {
        case MotionEvent.ACTION_DOWN:
          mTrackingCenter = inCenter;
          if (inCenter) {
            mHighlightCenter = true;
            invalidate();
            break;
          }
        case MotionEvent.ACTION_MOVE:
          if (mTrackingCenter) {
            if (mHighlightCenter != inCenter) {
              mHighlightCenter = inCenter;
              invalidate();
            }
          } else {
            float angle = (float) Math.atan2(y, x);
            // need to turn angle [-PI ... PI] into unit [0....1]
            float unit = angle / (2 * PI);
            if (unit < 0) {
              unit += 1;
            }
            mCenterPaint.setColor(interpColor(mColors, unit));
            invalidate();
          }
          break;
        case MotionEvent.ACTION_UP:
          playSoundEffect(
              SoundEffectConstants.CLICK); // play the default button click (respects prefs)
          if (mTrackingCenter) {
            if (inCenter) {
              mListener.colorChanged(mCenterPaint.getColor());
            }
            mTrackingCenter = false; // so we draw w/o halo
            invalidate();
          }
          break;
      }
      return true;
    }
    @SuppressLint("FloatMath")
    @Override
    public boolean onTouchEvent(MotionEvent event) {
      float x = event.getX() - CENTER_X;
      float y = event.getY() - CENTER_Y;
      boolean inCenter = java.lang.Math.sqrt(x * x + y * y) <= CENTER_RADIUS;

      switch (event.getAction()) {
        case MotionEvent.ACTION_DOWN:
          mTrackingCenter = inCenter;
          if (inCenter) {
            mHighlightCenter = true;
            invalidate();
            break;
          }
        case MotionEvent.ACTION_MOVE:
          if (mTrackingCenter) {
            if (mHighlightCenter != inCenter) {
              mHighlightCenter = inCenter;
              invalidate();
            }
          } else {
            float angle = (float) java.lang.Math.atan2(y, x);
            // need to turn angle [-PI ... PI] into unit [0....1]
            float unit = angle / (2 * PI);
            if (unit < 0) {
              unit += 1;
            }
            mCenterPaint.setColor(interpColor(mColors, unit));
            invalidate();
          }
          break;
        case MotionEvent.ACTION_UP:
          if (mTrackingCenter) {
            if (inCenter) {
              mListener.colorChanged(mCenterPaint.getColor());
            }
            mTrackingCenter = false; // so we draw w/o halo
            invalidate();
          }
          break;
      }
      return true;
    }
    /** Process touch events: down, move, and up */
    @Override
    public boolean onTouchEvent(MotionEvent event) {
      float x = event.getX();
      float y = event.getY();

      // Generate coordinates which are palette=local with the origin at the upper left of the main
      // 2D palette
      int y2 = (int) (pin(round(y - PALETTE_POS_Y), PALETTE_DIM));

      // Generate coordinates which are palette-local with the origin at the center of the main 2D
      // palette
      float circlePinnedX = x - PALETTE_POS_X - PALETTE_CENTER_X;
      float circlePinnedY = y - PALETTE_POS_Y - PALETTE_CENTER_Y;

      // Is the event in a swatch?
      boolean inSwatchOld = ptInRect(round(x), round(y), mOldSwatchRect);
      boolean inSwatchNew = ptInRect(round(x), round(y), mNewSwatchRect);

      // Get the event's distance from the center of the main 2D palette
      float radius =
          (float)
              java.lang.Math.sqrt(circlePinnedX * circlePinnedX + circlePinnedY * circlePinnedY);

      // Is the event in a circle-pinned 2D palette?
      boolean inOvalPalette = radius <= PALETTE_RADIUS;

      // Pin the radius
      if (radius > PALETTE_RADIUS) radius = PALETTE_RADIUS;

      // Is the event in a vertical slider to the right of the main 2D palette
      boolean inVerSlider = ptInRect(round(x), round(y), mVerSliderRect);

      switch (event.getAction()) {
        case MotionEvent.ACTION_DOWN:
          mTracking = TRACKED_NONE;

          if (inSwatchOld) mTracking = TRACK_SWATCH_OLD;
          else if (inSwatchNew) mTracking = TRACK_SWATCH_NEW;

          // NEW_METHOD_WORK_NEEDED_HERE
          // To add a new method, replicate and extend the last entry in this list
          else if (mMethod == METHOD_HS_V_PALETTE) {
            if (inOvalPalette) {
              mTracking = TRACK_HS_PALETTE;
              mFocusedControl = 0;
            } else if (inVerSlider) {
              mTracking = TRACK_VER_VALUE_SLIDER;
              mFocusedControl = 1;
            }
          }
        case MotionEvent.ACTION_MOVE:
          // NEW_METHOD_WORK_NEEDED_HERE
          // To add a new method, replicate and extend the entries in this list,
          // one per UI controller the new method requires.
          if (mTracking == TRACK_HS_PALETTE) {
            float angle = (float) java.lang.Math.atan2(circlePinnedY, circlePinnedX);
            // need to turn angle [-PI ... PI] into unit [0....1]
            float unit = angle / (2 * PI);
            if (unit < 0) {
              unit += 1;
            }

            mCoord[0] = round(Math.cos(angle) * radius);
            mCoord[1] = round(Math.sin(angle) * radius);

            int c = interpColor(mSpectrumColorsRev, unit);
            float[] hsv = new float[3];
            Color.colorToHSV(c, hsv);
            mHSV[0] = hsv[0];
            mHSV[1] = radius / PALETTE_RADIUS;
            updateAllFromHSV();
            mSwatchNew.setColor(Color.HSVToColor(mHSV));

            setVerValSlider();

            invalidate();
          } else if (mTracking == TRACK_VER_VALUE_SLIDER) {
            if (mCoord[2] != y2) {
              mCoord[2] = y2;
              float value = 1.0f - (float) y2 / (float) PALETTE_DIM;

              mHSV[2] = value;
              updateAllFromHSV();
              mSwatchNew.setColor(Color.HSVToColor(mHSV));

              setOvalValDimmer();

              invalidate();
            }
          }
          break;
        case MotionEvent.ACTION_UP:
          // NEW_METHOD_WORK_NEEDED_HERE
          // To add a new method, replicate and extend the last entry in this list.
          if (mTracking == TRACK_SWATCH_OLD && inSwatchOld) {
            Color.colorToHSV(mOriginalColor, mHSV);
            mSwatchNew.setColor(mOriginalColor);
            initUI();
            invalidate();
          } else if (mTracking == TRACK_SWATCH_NEW && inSwatchNew) {
            mListener.colorChanged(mSwatchNew.getColor());
            invalidate();
          }

          mTracking = TRACKED_NONE;
          break;
      }

      return true;
    }
    @Override
    public boolean onTouchEvent(MotionEvent event) {
      float x = event.getX() - CENTER_X;
      float y = event.getY() - CENTER_Y;
      boolean inCenter = java.lang.Math.sqrt(x * x + y * y) <= CENTER_RADIUS;

      switch (event.getAction()) {
        case MotionEvent.ACTION_DOWN:
          mTrackingCenter = inCenter;
          if (inCenter) {
            mHighlightCenter = true;
            invalidate();
            break;
          }
        case MotionEvent.ACTION_MOVE:
          if (mTrackingCenter) {
            if (mHighlightCenter != inCenter) {
              mHighlightCenter = inCenter;
              invalidate();
            }
          } else if ((x >= -100 & x <= 100) && (y <= 130 && y >= 110)) // see
          // if
          // we're
          // in
          // the
          // hsv
          // slider
          {
            int a, r, g, b, c0, c1;
            float p;

            // set the center paint to this color

            if (x < 0) {
              c0 = mHSVColors[0];
              c1 = mHSVColors[1];
              p = (x + 100) / 100;
            } else {
              c0 = mHSVColors[1];
              c1 = mHSVColors[2];
              p = x / 100;
            }

            a = ave(Color.alpha(c0), Color.alpha(c1), p);
            r = ave(Color.red(c0), Color.red(c1), p);
            g = ave(Color.green(c0), Color.green(c1), p);
            b = ave(Color.blue(c0), Color.blue(c1), p);

            mCenterPaint.setColor(Color.argb(a, r, g, b));

            mRedrawHSV = false;
            invalidate();
          } else {
            float angle = (float) java.lang.Math.atan2(y, x);
            // need to turn angle [-PI ... PI] into unit [0....1]

            float unit = angle / (2 * PI);
            if (unit < 0) {
              unit += 1;
            }
            mCenterPaint.setColor(interpColor(mColors, unit));
            invalidate();
          }
          break;
        case MotionEvent.ACTION_UP:
          if (mTrackingCenter) {
            if (inCenter) {
              mListener.colorChanged(mCenterPaint.getColor());
            }
            mTrackingCenter = false; // so we draw w/o halo
            invalidate();
          }
          break;
      }
      return true;
    }