Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
#include "tundo.h"
Toshihiro Shimizu 890ddd
#include "tthreadmessage.h"
Toshihiro Shimizu 890ddd
#include "tvectorimage.h"
Toshihiro Shimizu 890ddd
#include "drawutil.h"
Toshihiro Shimizu 890ddd
#include "controlpointselection.h"
Toshihiro Shimizu 890ddd
#include "tproperty.h"
Toshihiro Shimizu 890ddd
#include "tenv.h"
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
#include "tools/tool.h"
Toshihiro Shimizu 890ddd
#include "tools/toolutils.h"
Toshihiro Shimizu 890ddd
#include "tools/cursors.h"
Toshihiro Shimizu 890ddd
#include "tools/toolhandle.h"
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
#include "toonz/tframehandle.h"
Toshihiro Shimizu 890ddd
#include "toonz/tcolumnhandle.h"
Toshihiro Shimizu 890ddd
#include "toonz/txsheethandle.h"
Toshihiro Shimizu 890ddd
#include "toonz/txshlevelhandle.h"
Toshihiro Shimizu 890ddd
#include "toonz/tobjecthandle.h"
Toshihiro Shimizu 890ddd
#include "toonz/stage2.h"
Toshihiro Shimizu 890ddd
#include "toonz/tstageobject.h"
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
#include "tw/keycodes.h"
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
// For Qt translation support
Toshihiro Shimizu 890ddd
#include <qcoreapplication></qcoreapplication>
shun_iwasawa d51821
#include <qkeyevent></qkeyevent>
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
using namespace ToolUtils;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
TEnv::IntVar AutoSelectDrawing("ControlPointEditorToolAutoSelectDrawing", 1);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-----------------------------------------------------------------------------
Shinya Kitaoka 120a6e
namespace {
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
/*! Restituisce i parametri riferiti allo stroke della curva che si vuole
Shinya Kitaoka 120a6e
   muovere.
Shinya Kitaoka 120a6e
    I parametri dipendono da come sono i punti in \b beforeIndex, \b nextIndex
Shinya Kitaoka 120a6e
   (cuspidi, lineari).
Shinya Kitaoka 120a6e
    Puo' restituire due range nei casi in cui lo stroke e' selfLoop e la curva
Shinya Kitaoka 120a6e
   e' a cavallo del punto di chiusura.
Toshihiro Shimizu 890ddd
*/
Shinya Kitaoka 120a6e
void getSegmentParameter(ControlPointEditorStroke *cpEditor, int beforeIndex,
Shinya Kitaoka 120a6e
                         int nextIndex, double &w0, double &w1, double &q0,
Shinya Kitaoka 120a6e
                         double &q1) {
Shinya Kitaoka 120a6e
  TStroke *stroke = cpEditor->getStroke();
Shinya Kitaoka 120a6e
  if (!stroke) return;
Shinya Kitaoka 120a6e
  q0 = q1 = w0 = w1 = -1;
Shinya Kitaoka 120a6e
  int cpCount       = cpEditor->getControlPointCount();
Shinya Kitaoka 120a6e
  // Il punto di controllo precedente non e' lincato
Shinya Kitaoka 120a6e
  if (cpEditor->isSpeedOutLinear(beforeIndex) ||
Shinya Kitaoka 120a6e
      cpEditor->isSpeedInLinear(beforeIndex) || cpEditor->isCusp(beforeIndex)) {
Shinya Kitaoka 120a6e
    if (cpEditor->isSelfLoop() && beforeIndex == 0 &&
Shinya Kitaoka 120a6e
        nextIndex == cpCount - 1)  // Nel caso selfLoop si invertono i valori
Shinya Kitaoka 120a6e
      w1 = 1;
Shinya Kitaoka 120a6e
    else
Shinya Kitaoka 120a6e
      w0 = stroke->getParameterAtControlPoint(
Shinya Kitaoka 120a6e
          cpEditor->getIndexPointInStroke(beforeIndex));
Shinya Kitaoka 120a6e
  } else  // Punto di controllo precedente lincato
Shinya Kitaoka 120a6e
  {
Shinya Kitaoka 120a6e
    if (!cpEditor->isSelfLoop() || beforeIndex != 0)
Shinya Kitaoka 120a6e
      w0 = stroke->getParameterAtControlPoint(
Shinya Kitaoka 120a6e
          cpEditor->getIndexPointInStroke(beforeIndex) - 4);
Shinya Kitaoka 120a6e
    else {
Shinya Kitaoka 120a6e
      if (nextIndex == 1)  // Primo chunk
Shinya Kitaoka 120a6e
      {
Shinya Kitaoka 120a6e
        w0 = 0;
Shinya Kitaoka 120a6e
        q0 = stroke->getParameterAtControlPoint(
Shinya Kitaoka 120a6e
            cpEditor->getIndexPointInStroke(cpCount - 1));
Shinya Kitaoka 120a6e
        q1 = 1;
Shinya Kitaoka 120a6e
      } else if (nextIndex == cpCount - 1)  // Ultimo chunk
Shinya Kitaoka 120a6e
      {
Shinya Kitaoka 120a6e
        w1 = 1;
Shinya Kitaoka 120a6e
        q0 = 0;
Shinya Kitaoka 120a6e
        q1 = stroke->getParameterAtControlPoint(
Shinya Kitaoka 120a6e
            cpEditor->getIndexPointInStroke(1));
Shinya Kitaoka 120a6e
      } else {
Shinya Kitaoka 120a6e
        assert(0);
Shinya Kitaoka 120a6e
      }  // Non dovrebbe mai accadere
Shinya Kitaoka 120a6e
    }
Shinya Kitaoka 120a6e
  }
Shinya Kitaoka 120a6e
  // Il punto di controllo successivo non e' lincato
Shinya Kitaoka 120a6e
  if (cpEditor->isSpeedInLinear(nextIndex) ||
Shinya Kitaoka 120a6e
      cpEditor->isSpeedOutLinear(nextIndex) || cpEditor->isCusp(nextIndex)) {
Shinya Kitaoka 120a6e
    if (cpEditor->isSelfLoop() && beforeIndex == 0 &&
Shinya Kitaoka 120a6e
        nextIndex == cpCount - 1)  // Nel caso selfLoop si invertono i valori
Shinya Kitaoka 120a6e
      w0 = stroke->getParameterAtControlPoint(
Shinya Kitaoka 120a6e
          cpEditor->getIndexPointInStroke(nextIndex));
Shinya Kitaoka 120a6e
    else
Shinya Kitaoka 120a6e
      w1 = stroke->getParameterAtControlPoint(
Shinya Kitaoka 120a6e
          cpEditor->getIndexPointInStroke(nextIndex));
Shinya Kitaoka 120a6e
  } else  // Punto di controllo successivo lincato
Shinya Kitaoka 120a6e
  {
Shinya Kitaoka 120a6e
    if (!cpEditor->isSelfLoop() || nextIndex != cpCount - 1 || beforeIndex != 0)
Shinya Kitaoka 120a6e
      w1 = stroke->getParameterAtControlPoint(
Shinya Kitaoka 120a6e
          cpEditor->getIndexPointInStroke(nextIndex) + 4);
Shinya Kitaoka 120a6e
    else if (nextIndex == cpCount - 1)  // Ultimo chunk
Shinya Kitaoka 120a6e
      w0 = stroke->getParameterAtControlPoint(
Shinya Kitaoka 120a6e
          cpEditor->getIndexPointInStroke(nextIndex) - 4);
Shinya Kitaoka 120a6e
    else {
Shinya Kitaoka 120a6e
      assert(0);
Shinya Kitaoka 120a6e
    }  // Non dovrebbe mai accadere, i vari casi dovrebbero essere gestiti sopra
Shinya Kitaoka 120a6e
  }
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
}  // namespace
Toshihiro Shimizu 890ddd
//=============================================================================
Toshihiro Shimizu 890ddd
// ControlPointEditorTool
Toshihiro Shimizu 890ddd
//-----------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka d1f6c4
class ControlPointEditorTool final : public TTool {
Shinya Kitaoka 120a6e
  Q_DECLARE_TR_FUNCTIONS(ControlPointEditorTool)
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  bool m_draw;
Shinya Kitaoka 120a6e
  bool m_isMenuViewed;
Shinya Kitaoka 120a6e
  int m_lastPointSelected;
Shinya Kitaoka 120a6e
  bool m_isImageChanged;
Shinya Kitaoka 120a6e
  ControlPointSelection m_selection;
Shinya Kitaoka 120a6e
  ControlPointEditorStroke m_controlPointEditorStroke;
Shinya Kitaoka 120a6e
  std::pair<int, int=""> m_moveSegmentLimitation;  // Indici dei punti di controllo</int,>
Shinya Kitaoka 120a6e
                                                // che limitano la curva da
Shinya Kitaoka 120a6e
                                                // muovere
Shinya Kitaoka 120a6e
  ControlPointEditorStroke m_moveControlPointEditorStroke;  // Usate per muovere
Shinya Kitaoka 120a6e
                                                            // la curva durante
Shinya Kitaoka 120a6e
                                                            // il drag.
Shinya Kitaoka 120a6e
  TRectD m_selectingRect;
Shinya Kitaoka 120a6e
  TPointD m_pos;
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  TPropertyGroup m_prop;
Shinya Kitaoka 120a6e
  TBoolProperty
Shinya Kitaoka 120a6e
      m_autoSelectDrawing;  // Consente di scegliere se swichare tra i livelli.
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  enum Action {
Shinya Kitaoka 120a6e
    NONE,
Shinya Kitaoka 120a6e
    RECT_SELECTION,
Shinya Kitaoka 120a6e
    CP_MOVEMENT,
Shinya Kitaoka 120a6e
    SEGMENT_MOVEMENT,
Shinya Kitaoka 120a6e
    IN_SPEED_MOVEMENT,
Shinya Kitaoka 120a6e
    OUT_SPEED_MOVEMENT
Shinya Kitaoka 120a6e
  };
Shinya Kitaoka 120a6e
  Action m_action;
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  enum CursorType { NORMAL, ADD, EDIT_SPEED, EDIT_SEGMENT, NO_ACTIVE };
Shinya Kitaoka 120a6e
  CursorType m_cursorType;
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  TUndo *m_undo;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
public:
Shinya Kitaoka 120a6e
  ControlPointEditorTool();
Toshihiro Shimizu 890ddd
Shinya Kitaoka 473e70
  ToolType getToolType() const override { return TTool::LevelWriteTool; }
Toshihiro Shimizu 890ddd
Shinya Kitaoka 473e70
  void updateTranslation() override;
Toshihiro Shimizu 890ddd
Shinya Kitaoka 473e70
  TPropertyGroup *getProperties(int targetType) override { return &m_prop; }
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  // da TSelectionOwner: chiamato quando la selezione corrente viene cambiata
Shinya Kitaoka 120a6e
  void onSelectionChanged() { invalidate(); }
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  // da TSelectionOwner: chiamato quando si vuole ripristinare una vecchia
Shinya Kitaoka 120a6e
  // selezione
Shinya Kitaoka 120a6e
  // attualmente non usato
Shinya Kitaoka 120a6e
  bool select(const TSelection *) { return false; }
Shinya Kitaoka 120a6e
  ControlPointEditorStroke getControlPointEditorStroke() {
Shinya Kitaoka 120a6e
    return m_controlPointEditorStroke;
Shinya Kitaoka 120a6e
  };
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  void initUndo();
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  void getNearestStrokeColumnIndexes(std::vector<int> &indexes, TPointD pos);</int>
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  void drawMovingSegment();
Shinya Kitaoka 120a6e
  void drawControlPoint();
Shinya Kitaoka 473e70
  void draw() override;
Shinya Kitaoka 473e70
  void mouseMove(const TPointD &pos, const TMouseEvent &e) override;
Shinya Kitaoka 473e70
  void leftButtonDown(const TPointD &pos, const TMouseEvent &e) override;
Shinya Kitaoka 473e70
  void rightButtonDown(const TPointD &pos, const TMouseEvent &) override;
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  void moveControlPoints(const TPointD &delta);
Shinya Kitaoka 120a6e
  void moveSpeed(const TPointD &delta, bool isIn);
Shinya Kitaoka 120a6e
  void moveSegment(const TPointD &delta, bool dragging, bool isShiftPressed);
Toshihiro Shimizu 890ddd
Shinya Kitaoka 473e70
  void leftButtonDrag(const TPointD &pos, const TMouseEvent &e) override;
Shinya Kitaoka 473e70
  void leftButtonUp(const TPointD &pos, const TMouseEvent &e) override;
Shinya Kitaoka 473e70
  void addContextMenuItems(QMenu *menu) override;
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  void linkSpeedInOut(int index);
Shinya Kitaoka 120a6e
  void unlinkSpeedInOut(int pointIndex);
Toshihiro Shimizu 890ddd
Shinya Kitaoka 473e70
  bool keyDown(int key, TUINT32 flags, const TPoint &pos) override;
Shinya Kitaoka 473e70
  void onEnter() override;
Shinya Kitaoka 473e70
  void onLeave() override;
Shinya Kitaoka 473e70
  bool onPropertyChanged(std::string propertyName) override;
Toshihiro Shimizu 890ddd
Shinya Kitaoka 473e70
  void onActivate() override;
Shinya Kitaoka 473e70
  void onDeactivate() override;
Shinya Kitaoka 473e70
  void onImageChanged() override;
Shinya Kitaoka 473e70
  int getCursorId() const override;
Toshihiro Shimizu 890ddd
shun_iwasawa d51821
  // returns true if the pressed key is recognized and processed.
shun_iwasawa d51821
  bool isEventAcceptable(QEvent *e) override;
shun_iwasawa d51821
Toshihiro Shimizu 890ddd
} controlPointEditorTool;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//=============================================================================
Toshihiro Shimizu 890ddd
// Spline Editor Tool
Toshihiro Shimizu 890ddd
//-----------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
ControlPointEditorTool::ControlPointEditorTool()
Shinya Kitaoka 120a6e
    : TTool("T_ControlPointEditor")
Shinya Kitaoka 120a6e
    , m_draw(false)
Shinya Kitaoka 120a6e
    , m_lastPointSelected(-1)
Shinya Kitaoka 120a6e
    , m_isImageChanged(false)
Shinya Kitaoka 120a6e
    , m_selectingRect(TRectD())
Shinya Kitaoka 120a6e
    , m_autoSelectDrawing("Auto Select Drawing", true)
Shinya Kitaoka 120a6e
    , m_action(NONE)
Shinya Kitaoka 120a6e
    , m_cursorType(NORMAL)
Shinya Kitaoka 120a6e
    , m_undo(0)
Shinya Kitaoka 120a6e
    , m_isMenuViewed(false)
Shinya Kitaoka 120a6e
    , m_moveControlPointEditorStroke()
Shinya Kitaoka 120a6e
    , m_moveSegmentLimitation() {
Shinya Kitaoka 120a6e
  bind(TTool::Vectors);
Shinya Kitaoka 120a6e
  m_prop.bind(m_autoSelectDrawing);
Shinya Kitaoka 120a6e
  m_selection.setControlPointEditorStroke(&m_controlPointEditorStroke);
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  m_autoSelectDrawing.setId("AutoSelectDrawing");
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-----------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
void ControlPointEditorTool::updateTranslation() {
Shinya Kitaoka 120a6e
  m_autoSelectDrawing.setQStringName(tr("Auto Select Drawing"));
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//---------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
void ControlPointEditorTool::initUndo() {
Shinya Kitaoka 120a6e
  if (TTool::getApplication()->getCurrentObject()->isSpline()) {
Shinya Kitaoka 120a6e
    m_undo =
Shinya Kitaoka 120a6e
        new UndoPath(getXsheet()->getStageObject(getObjectId())->getSpline());
Shinya Kitaoka 120a6e
    return;
Shinya Kitaoka 120a6e
  }
Shinya Kitaoka 120a6e
  TVectorImageP vi(getImage(false));
Shinya Kitaoka 120a6e
  if (!vi) return;
Shinya Kitaoka 120a6e
  TXshSimpleLevel *level =
Shinya Kitaoka 120a6e
      TTool::getApplication()->getCurrentLevel()->getSimpleLevel();
Shinya Kitaoka 120a6e
  UndoControlPointEditor *undo =
Shinya Kitaoka 120a6e
      new UndoControlPointEditor(level, getCurrentFid());
Shinya Kitaoka 120a6e
  int index = m_controlPointEditorStroke.getStrokeIndex();
Shinya Kitaoka 120a6e
  if (index > -1) undo->addOldStroke(index, vi->getVIStroke(index));
Shinya Kitaoka 120a6e
  m_undo = undo;
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//---------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
void ControlPointEditorTool::getNearestStrokeColumnIndexes(
Shinya Kitaoka 120a6e
    std::vector<int> &indexes, TPointD pos) {</int>
Shinya Kitaoka 120a6e
  TTool::Application *app = TTool::getApplication();
Shinya Kitaoka 120a6e
  TXsheet *xsh            = app->getCurrentXsheet()->getXsheet();
Shinya Kitaoka 120a6e
  int currentFrame        = app->getCurrentFrame()->getFrameIndex();
Shinya Kitaoka 120a6e
  std::vector<int> newIndexes;</int>
Shinya Kitaoka 120a6e
  TAffine aff = getMatrix();
Shinya Kitaoka 120a6e
  int i       = 0;
Shinya Kitaoka 120a6e
  for (i = 0; i < (int)indexes.size(); i++) {
Shinya Kitaoka 120a6e
    if (xsh->getColumn(i)->isLocked()) continue;
Shinya Kitaoka 120a6e
    int index        = indexes[i];
Shinya Kitaoka 120a6e
    TVectorImageP vi = xsh->getCell(currentFrame, index).getImage(false);
Shinya Kitaoka 120a6e
    if (!vi) continue;
Shinya Kitaoka 120a6e
    double dist2, t = 0;
Shinya Kitaoka 120a6e
    UINT strokeIndex = -1;
Shinya Kitaoka 120a6e
    TPointD p        = getColumnMatrix(index).inv() * getMatrix() * pos;
Shinya Kitaoka 120a6e
    if (vi->getNearestStroke(p, t, strokeIndex, dist2) &&
Shinya Kitaoka 120a6e
        dist2 < 25 * getPixelSize() * getPixelSize())
Shinya Kitaoka 120a6e
      newIndexes.push_back(index);
Shinya Kitaoka 120a6e
  }
Shinya Kitaoka 120a6e
  indexes.clear();
Shinya Kitaoka 120a6e
  indexes = newIndexes;
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//---------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
void ControlPointEditorTool::drawMovingSegment() {
Shinya Kitaoka 120a6e
  int beforeIndex = m_moveSegmentLimitation.first;
Shinya Kitaoka 120a6e
  int nextIndex   = m_moveSegmentLimitation.second;
Shinya Kitaoka 120a6e
  if (m_action != EDIT_SEGMENT || beforeIndex == -1 || nextIndex == -1 ||
Shinya Kitaoka 120a6e
      !m_moveControlPointEditorStroke.getStroke())
Shinya Kitaoka 120a6e
    return;
Shinya Kitaoka 120a6e
  tglColor(TPixel::Green);
Shinya Kitaoka 120a6e
  double w0, w1;
Shinya Kitaoka 120a6e
  double q0, q1;
Shinya Kitaoka 120a6e
  getSegmentParameter(&m_moveControlPointEditorStroke, beforeIndex, nextIndex,
Shinya Kitaoka 120a6e
                      w0, w1, q0, q1);
Shinya Kitaoka 120a6e
  if (w0 != -1 && w1 != -1)  // Dovrebbero essere sempre diversi...
Shinya Kitaoka 120a6e
    drawStrokeCenterline(*m_moveControlPointEditorStroke.getStroke(),
Shinya Kitaoka 120a6e
                         getPixelSize(), w0, w1);
Shinya Kitaoka 120a6e
  if (q0 != -1 && q1 != -1)
Shinya Kitaoka 120a6e
    drawStrokeCenterline(*m_moveControlPointEditorStroke.getStroke(),
Shinya Kitaoka 120a6e
                         getPixelSize(), q0, q1);
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//---------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
void ControlPointEditorTool::drawControlPoint() {
Shinya Kitaoka 120a6e
  TPixel color1         = TPixel(79, 128, 255);
Shinya Kitaoka 120a6e
  TPixel color2         = TPixel::White;
Shinya Kitaoka 120a6e
  TPixel color_handle   = TPixel(96, 64, 201);
Shinya Kitaoka 120a6e
  int controlPointCount = m_controlPointEditorStroke.getControlPointCount();
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  double pix    = getPixelSize() * 2.0f;
Shinya Kitaoka 120a6e
  double pix1_5 = 1.5 * pix, pix2 = pix + pix, pix2_5 = pix1_5 + pix,
Shinya Kitaoka 120a6e
         pix3 = pix2 + pix, pix3_5 = pix2_5 + pix, pix4 = pix3 + pix;
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  double maxDist2 = sq(5.0 * pix);
Shinya Kitaoka 120a6e
  double dist2    = 0;
Shinya Kitaoka 120a6e
  int pointIndex;
Shinya Kitaoka 120a6e
  ControlPointEditorStroke::PointType pointType =
Shinya Kitaoka 120a6e
      m_controlPointEditorStroke.getPointTypeAt(m_pos, maxDist2, pointIndex);
Shinya Kitaoka 120a6e
  int i;
Shinya Kitaoka 120a6e
  for (i = 0; i < controlPointCount; i++) {
Shinya Kitaoka 120a6e
    TThickPoint point = m_controlPointEditorStroke.getControlPoint(i);
Shinya Kitaoka 120a6e
    TPointD pa        = m_controlPointEditorStroke.getSpeedInPoint(i);
Shinya Kitaoka 120a6e
    TPointD pb        = m_controlPointEditorStroke.getSpeedOutPoint(i);
Shinya Kitaoka 120a6e
    tglColor(color_handle);
Shinya Kitaoka 120a6e
    tglDrawSegment(pa, point);
Shinya Kitaoka 120a6e
    if (i == pointIndex && pointType == ControlPointEditorStroke::SPEED_IN)
Shinya Kitaoka 120a6e
      tglFillRect(pa.x - pix2_5, pa.y - pix2_5, pa.x + pix2_5, pa.y + pix2_5);
Shinya Kitaoka 120a6e
    else
Shinya Kitaoka 120a6e
      tglFillRect(pa.x - pix1_5, pa.y - pix1_5, pa.x + pix1_5, pa.y + pix1_5);
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
    tglDrawSegment(pb, point);
Shinya Kitaoka 120a6e
    if (i == pointIndex && pointType == ControlPointEditorStroke::SPEED_OUT)
Shinya Kitaoka 120a6e
      tglFillRect(pb.x - pix2_5, pb.y - pix2_5, pb.x + pix2_5, pb.y + pix2_5);
Shinya Kitaoka 120a6e
    else
Shinya Kitaoka 120a6e
      tglFillRect(pb.x - pix1_5, pb.y - pix1_5, pb.x + pix1_5, pb.y + pix1_5);
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
    tglColor(color1);
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
    if (i == pointIndex &&
Shinya Kitaoka 120a6e
        pointType == ControlPointEditorStroke::CONTROL_POINT) {
Shinya Kitaoka 120a6e
      tglFillRect(point.x - pix3_5, point.y - pix3_5, point.x + pix3_5,
Shinya Kitaoka 120a6e
                  point.y + pix3_5);
Shinya Kitaoka 120a6e
      if (!m_selection.isSelected(i)) {
Shinya Kitaoka 120a6e
        tglColor(color2);
Shinya Kitaoka 120a6e
        tglFillRect(point.x - pix2_5, point.y - pix2_5, point.x + pix2_5,
Shinya Kitaoka 120a6e
                    point.y + pix2_5);
Shinya Kitaoka 120a6e
      }
Shinya Kitaoka 120a6e
    } else {
Shinya Kitaoka 120a6e
      tglFillRect(point.x - pix2, point.y - pix2, point.x + pix2,
Shinya Kitaoka 120a6e
                  point.y + pix2);
Shinya Kitaoka 120a6e
      if (!m_selection.isSelected(i)) {
Shinya Kitaoka 120a6e
        tglColor(color2);
Shinya Kitaoka 120a6e
        tglFillRect(point.x - pix, point.y - pix, point.x + pix, point.y + pix);
Shinya Kitaoka 120a6e
      }
Shinya Kitaoka 120a6e
    }
Shinya Kitaoka 120a6e
  }
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//---------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
void ControlPointEditorTool::draw() {
Shinya Kitaoka 120a6e
  TVectorImageP vi(getImage(false));
Shinya Kitaoka 120a6e
  if (!m_draw) return;
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  int currentStroke = m_controlPointEditorStroke.getStrokeIndex();
Shinya Kitaoka 120a6e
  if (!vi || currentStroke == -1 ||
Shinya Kitaoka 120a6e
      m_controlPointEditorStroke.getControlPointCount() == 0 ||
Shinya Kitaoka 120a6e
      vi->getStrokeCount() == 0 || (int)vi->getStrokeCount() <= currentStroke) {
Shinya Kitaoka 120a6e
    m_controlPointEditorStroke.setStroke((TVectorImage *)0, -1);
Shinya Kitaoka 120a6e
    return;
Shinya Kitaoka 120a6e
  }
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  TPixel color1, color2;
Shinya Kitaoka 120a6e
  if (m_action == RECT_SELECTION)  // Disegna il rettangolo per la selezione
Shinya Kitaoka 120a6e
  {
Shinya Kitaoka 120a6e
    color1 = TPixel32::
Shinya Kitaoka 120a6e
        Black;  // TransparencyCheck::instance()->isEnabled()?TPixel32::White:TPixel32::Black;
Shinya Kitaoka 120a6e
    drawRect(m_selectingRect, color1, 0x3F33, true);
Shinya Kitaoka 120a6e
  }
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  if (m_controlPointEditorStroke.getControlPointCount() <= 0) return;
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  color1          = TPixel(79, 128, 255);
Shinya Kitaoka 120a6e
  color2          = TPixel::White;
Shinya Kitaoka 120a6e
  TStroke *stroke = m_controlPointEditorStroke.getStroke();
Shinya Kitaoka 120a6e
  tglColor(color1);
Shinya Kitaoka 120a6e
  drawStrokeCenterline(*stroke, getPixelSize());
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  drawControlPoint();
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  drawMovingSegment();
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//---------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
void ControlPointEditorTool::mouseMove(const TPointD &pos,
Shinya Kitaoka 120a6e
                                       const TMouseEvent &e) {
Shinya Kitaoka 120a6e
  // Scelgo il cursore in base alla distanza del mouse dalla curva e dai punti
Shinya Kitaoka 120a6e
  // di controllo
Shinya Kitaoka 120a6e
  TVectorImageP vi(getImage(false));
Shinya Kitaoka 120a6e
  if (!vi) {
Shinya Kitaoka 120a6e
    m_controlPointEditorStroke.setStroke((TVectorImage *)0, -1);
Shinya Kitaoka 120a6e
    m_cursorType = NO_ACTIVE;
Shinya Kitaoka 120a6e
    return;
Shinya Kitaoka 120a6e
  } else
Shinya Kitaoka 120a6e
    m_cursorType = NORMAL;
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  m_pos = pos;
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  if (!m_draw || m_controlPointEditorStroke.getStrokeIndex() == -1) return;
Shinya Kitaoka 120a6e
  if (e.isAltPressed())
Shinya Kitaoka 120a6e
    m_cursorType = EDIT_SPEED;
Shinya Kitaoka 120a6e
  else {
Shinya Kitaoka 120a6e
    double maxDist  = 5 * getPixelSize();
Shinya Kitaoka 120a6e
    double maxDist2 = maxDist * maxDist;
Shinya Kitaoka 120a6e
    int pointIndexCP;
Shinya Kitaoka 120a6e
    ControlPointEditorStroke::PointType pointType =
Shinya Kitaoka 120a6e
        m_controlPointEditorStroke.getPointTypeAt(pos, maxDist2, pointIndexCP);
Shinya Kitaoka 120a6e
    if (pointType == ControlPointEditorStroke::SEGMENT && e.isCtrlPressed())
Shinya Kitaoka 120a6e
      m_cursorType = ADD;
Shinya Kitaoka 120a6e
    // else if(pointType == ControlPointEditorStroke::SEGMENT)
Shinya Kitaoka 120a6e
    // m_cursorType=EDIT_SEGMENT;
Shinya Kitaoka 120a6e
    else
Shinya Kitaoka 120a6e
      m_cursorType = NORMAL;
Shinya Kitaoka 120a6e
  }
Shinya Kitaoka 120a6e
  invalidate();
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//---------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
void ControlPointEditorTool::leftButtonDown(const TPointD &pos,
Shinya Kitaoka 120a6e
                                            const TMouseEvent &e) {
Shinya Kitaoka 120a6e
  m_pos           = pos;
Shinya Kitaoka 120a6e
  double maxDist  = 5 * getPixelSize();
Shinya Kitaoka 120a6e
  double maxDist2 = maxDist * maxDist;
Shinya Kitaoka 120a6e
  double dist2    = 0;
Shinya Kitaoka 120a6e
  int pointIndex;
Shinya Kitaoka 120a6e
  ControlPointEditorStroke::PointType pointType =
Shinya Kitaoka 120a6e
      m_controlPointEditorStroke.getPointTypeAt(pos, maxDist2, pointIndex);
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  if (pointType == ControlPointEditorStroke::NONE) {
Shinya Kitaoka 120a6e
    // ho cliccato lontano dalla curva corrente
Shinya Kitaoka 120a6e
    TTool::Application *app = TTool::getApplication();
Shinya Kitaoka 120a6e
    if (m_autoSelectDrawing.getValue()) {
Shinya Kitaoka 120a6e
      // Non sono in nessun gadget
Shinya Kitaoka 120a6e
      std::vector<int> columnIndexes;</int>
Shinya Kitaoka 120a6e
      getViewer()->posToColumnIndexes(e.m_pos, columnIndexes,
Shinya Kitaoka 120a6e
                                      getPixelSize() * 5, false);
Shinya Kitaoka 120a6e
      getNearestStrokeColumnIndexes(columnIndexes, pos);
Shinya Kitaoka 120a6e
      if (!columnIndexes.empty()) {
Shinya Kitaoka 120a6e
        int currentColumnIndex = app->getCurrentColumn()->getColumnIndex();
Shinya Kitaoka 120a6e
        int columnIndex;
Shinya Kitaoka 120a6e
        if (columnIndexes.size() == 1)
Shinya Kitaoka 120a6e
          columnIndex = columnIndexes[0];
Shinya Kitaoka 120a6e
        else {
Shinya Kitaoka 120a6e
          ToolUtils::ColumChooserMenu *menu = new ToolUtils::ColumChooserMenu(
Shinya Kitaoka 120a6e
              app->getCurrentXsheet()->getXsheet(), columnIndexes);
Shinya Kitaoka 120a6e
          m_isMenuViewed = true;
Shinya Kitaoka 120a6e
          columnIndex    = menu->execute();
Shinya Kitaoka 120a6e
        }
Shinya Kitaoka 120a6e
        TXshColumn *column =
Shinya Kitaoka 120a6e
            app->getCurrentXsheet()->getXsheet()->getColumn(columnIndex);
Shinya Kitaoka 120a6e
        if (columnIndex >= 0 && columnIndex != currentColumnIndex && column &&
Shinya Kitaoka 120a6e
            !column->isLocked()) {
Shinya Kitaoka 120a6e
          TAffine aff = getMatrix();
Shinya Kitaoka 120a6e
          app->getCurrentColumn()->setColumnIndex(columnIndex);
Shinya Kitaoka 120a6e
          updateMatrix();
Shinya Kitaoka 120a6e
          currentColumnIndex = columnIndex;
Shinya Kitaoka 120a6e
          m_pos              = getMatrix().inv() * aff * pos;
Shinya Kitaoka 120a6e
        }
Shinya Kitaoka 120a6e
      }
Shinya Kitaoka 120a6e
    }
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
    TVectorImageP vi = getImage(false);
Shinya Kitaoka 120a6e
    if (!vi) return;
Shinya Kitaoka 120a6e
    double dist2, t = 0;
Shinya Kitaoka 120a6e
    UINT index = -1;
Shinya Kitaoka 120a6e
    if (vi->getNearestStroke(m_pos, t, index, dist2) &&
Shinya Kitaoka 120a6e
        dist2 < 25 * getPixelSize() * getPixelSize()) {
Shinya Kitaoka 120a6e
      // ho cliccato vicino alla curva index-esima
Shinya Kitaoka 120a6e
      assert(0 <= index && index < vi->getStrokeCount());
Shinya Kitaoka 120a6e
      m_controlPointEditorStroke.setStroke(vi, index);
Shinya Kitaoka 120a6e
      m_action = NONE;
Shinya Kitaoka 120a6e
      m_selection.makeCurrent();
Shinya Kitaoka 120a6e
    } else {
Shinya Kitaoka 120a6e
      // ho cliccato lontano da ogni altra curva
Shinya Kitaoka 120a6e
      m_selectingRect = TRectD(m_pos.x, m_pos.y, m_pos.x + 1, m_pos.y + 1);
Shinya Kitaoka 120a6e
      if (m_selectingRect.x0 > m_selectingRect.x1)
Shinya Kitaoka 120a6e
        tswap(m_selectingRect.x1, m_selectingRect.x0);
Shinya Kitaoka 120a6e
      if (m_selectingRect.y0 > m_selectingRect.y1)
Shinya Kitaoka 120a6e
        tswap(m_selectingRect.y1, m_selectingRect.y0);
Shinya Kitaoka 120a6e
      m_action = RECT_SELECTION;
Shinya Kitaoka 120a6e
    }
Shinya Kitaoka 120a6e
    m_selection.selectNone();
Shinya Kitaoka 120a6e
    return;
Shinya Kitaoka 120a6e
  }
Shinya Kitaoka 120a6e
  TVectorImageP vi = getImage(true);
Shinya Kitaoka 120a6e
  if (!vi) return;
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  if (pointType == ControlPointEditorStroke::SPEED_IN ||
Shinya Kitaoka 120a6e
      pointType == ControlPointEditorStroke::SPEED_OUT) {
Shinya Kitaoka 120a6e
    bool isIn = pointType == ControlPointEditorStroke::SPEED_IN;
Shinya Kitaoka 120a6e
    m_selection.selectNone();
Shinya Kitaoka 120a6e
    m_selection.select(pointIndex);
Shinya Kitaoka 120a6e
    m_action = isIn ? IN_SPEED_MOVEMENT : OUT_SPEED_MOVEMENT;
Shinya Kitaoka 120a6e
    if (e.isAltPressed()) {
Shinya Kitaoka 120a6e
      initUndo();
Shinya Kitaoka 120a6e
      if (m_controlPointEditorStroke.isCusp(pointIndex))
Shinya Kitaoka 120a6e
        linkSpeedInOut(pointIndex);
Shinya Kitaoka 120a6e
      else
Shinya Kitaoka 120a6e
        unlinkSpeedInOut(pointIndex);
Shinya Kitaoka 120a6e
      TUndoManager::manager()->add(m_undo);
Shinya Kitaoka 120a6e
      m_undo = 0;
Shinya Kitaoka 120a6e
    }
Shinya Kitaoka 120a6e
    m_selection.makeCurrent();
Shinya Kitaoka 120a6e
  } else if (pointType == ControlPointEditorStroke::CONTROL_POINT) {
Shinya Kitaoka 120a6e
    if (e.isAltPressed()) {
Shinya Kitaoka 120a6e
      m_selection.selectNone();
Shinya Kitaoka 120a6e
      m_selection.select(pointIndex);
Shinya Kitaoka 120a6e
      initUndo();
Shinya Kitaoka 120a6e
      bool isSpeedIn  = m_controlPointEditorStroke.isSpeedInLinear(pointIndex);
Shinya Kitaoka 120a6e
      bool isSpeedOut = m_controlPointEditorStroke.isSpeedOutLinear(pointIndex);
Shinya Kitaoka 120a6e
      m_controlPointEditorStroke.setLinear(pointIndex,
Shinya Kitaoka 120a6e
                                           !isSpeedIn && !isSpeedOut);
Shinya Kitaoka 120a6e
      TUndoManager::manager()->add(m_undo);
Shinya Kitaoka 120a6e
      m_undo = 0;
Shinya Kitaoka 120a6e
      return;
Shinya Kitaoka 120a6e
    }
Shinya Kitaoka 120a6e
    if (e.isCtrlPressed()) {
Shinya Kitaoka 120a6e
      if (m_selection.isSelected(pointIndex))
Shinya Kitaoka 120a6e
        m_selection.unselect(pointIndex);
Shinya Kitaoka 120a6e
      else
Shinya Kitaoka 120a6e
        m_selection.select(pointIndex);
Shinya Kitaoka 120a6e
    } else if (m_selection.isEmpty() || !m_selection.isSelected(pointIndex)) {
Shinya Kitaoka 120a6e
      m_selection.selectNone();
Shinya Kitaoka 120a6e
      m_selection.select(pointIndex);
Shinya Kitaoka 120a6e
    }
Shinya Kitaoka 120a6e
    m_lastPointSelected = pointIndex;
Shinya Kitaoka 120a6e
    m_action            = CP_MOVEMENT;
Shinya Kitaoka 120a6e
    m_selection.makeCurrent();
Shinya Kitaoka 120a6e
  } else if (pointType == ControlPointEditorStroke::SEGMENT &&
Shinya Kitaoka 120a6e
             !e.isAltPressed()) {
Shinya Kitaoka 120a6e
    m_selection.selectNone();
Shinya Kitaoka 120a6e
    if (e.isCtrlPressed()) {
Shinya Kitaoka 120a6e
      // Aggiungo un punto
Shinya Kitaoka 120a6e
      initUndo();
Shinya Kitaoka 120a6e
      pointIndex = m_controlPointEditorStroke.addControlPoint(pos);
Shinya Kitaoka 120a6e
      m_selection.select(pointIndex);
Shinya Kitaoka 120a6e
      m_action = CP_MOVEMENT;
Shinya Kitaoka 120a6e
      TUndoManager::manager()->add(m_undo);
Shinya Kitaoka 120a6e
      m_lastPointSelected = -1;
Shinya Kitaoka 120a6e
      notifyImageChanged();
Shinya Kitaoka 120a6e
    } else {
Shinya Kitaoka 120a6e
      // Inizio a muovere la curva
Shinya Kitaoka 120a6e
      int precPointIndex, nextPointIndex;
Shinya Kitaoka 120a6e
      precPointIndex = pointIndex;
Shinya Kitaoka 120a6e
      nextPointIndex =
Shinya Kitaoka 120a6e
          (m_controlPointEditorStroke.isSelfLoop() &&
Shinya Kitaoka 120a6e
           precPointIndex ==
Shinya Kitaoka 120a6e
               m_controlPointEditorStroke.getControlPointCount() - 1)
Shinya Kitaoka 120a6e
              ? 0
Shinya Kitaoka 120a6e
              : precPointIndex + 1;
Shinya Kitaoka 120a6e
      if (precPointIndex > -1 && nextPointIndex > -1) {
Shinya Kitaoka 120a6e
        if (precPointIndex > nextPointIndex)
Shinya Kitaoka 120a6e
          tswap(precPointIndex, nextPointIndex);
Shinya Kitaoka 120a6e
        m_moveSegmentLimitation.first  = precPointIndex;
Shinya Kitaoka 120a6e
        m_moveSegmentLimitation.second = nextPointIndex;
Shinya Kitaoka 120a6e
      }
Shinya Kitaoka 120a6e
      m_moveControlPointEditorStroke = *m_controlPointEditorStroke.clone();
Shinya Kitaoka 120a6e
      // Se e' premuto shift setto a cusp i due punti di controllo che
Shinya Kitaoka 120a6e
      // delimitano il segmento.
Shinya Kitaoka 120a6e
      if (e.isShiftPressed()) {
Shinya Kitaoka 120a6e
        if (!m_controlPointEditorStroke.isCusp(precPointIndex)) {
Shinya Kitaoka 120a6e
          m_controlPointEditorStroke.setCusp(precPointIndex, true, false);
Shinya Kitaoka 120a6e
          m_moveControlPointEditorStroke.setCusp(precPointIndex, true, false);
Shinya Kitaoka 120a6e
        }
Shinya Kitaoka 120a6e
        if (!m_controlPointEditorStroke.isCusp(nextPointIndex)) {
Shinya Kitaoka 120a6e
          m_controlPointEditorStroke.setCusp(nextPointIndex, true, true);
Shinya Kitaoka 120a6e
          m_moveControlPointEditorStroke.setCusp(nextPointIndex, true, true);
Shinya Kitaoka 120a6e
        }
Shinya Kitaoka 120a6e
      }
Shinya Kitaoka 120a6e
      m_action = SEGMENT_MOVEMENT;
Shinya Kitaoka 120a6e
    }
Shinya Kitaoka 120a6e
    m_selection.makeCurrent();
Shinya Kitaoka 120a6e
  }
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  int currentStroke = m_controlPointEditorStroke.getStrokeIndex();
Shinya Kitaoka 120a6e
  if (currentStroke != -1) initUndo();
Shinya Kitaoka 120a6e
  invalidate();
Shinya Kitaoka 120a6e
  m_isImageChanged = false;
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//---------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
void ControlPointEditorTool::rightButtonDown(const TPointD &pos,
Shinya Kitaoka 120a6e
                                             const TMouseEvent &) {
Shinya Kitaoka 120a6e
  TVectorImageP vi = getImage(true);
Shinya Kitaoka 120a6e
  if (!vi) return;
Shinya Kitaoka 120a6e
  double maxDist  = 5 * getPixelSize();
Shinya Kitaoka 120a6e
  double maxDist2 = maxDist * maxDist;
Shinya Kitaoka 120a6e
  double dist2    = 0;
Shinya Kitaoka 120a6e
  int pointIndex;
Shinya Kitaoka 120a6e
  ControlPointEditorStroke::PointType pointType =
Shinya Kitaoka 120a6e
      m_controlPointEditorStroke.getPointTypeAt(pos, maxDist2, pointIndex);
Shinya Kitaoka 120a6e
  if (pointType != ControlPointEditorStroke::CONTROL_POINT) return;
Shinya Kitaoka 120a6e
  m_selection.select(pointIndex);
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//---------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
void ControlPointEditorTool::moveControlPoints(const TPointD &delta) {
Shinya Kitaoka 120a6e
  int i;
Shinya Kitaoka 120a6e
  int cpCount = m_controlPointEditorStroke.getControlPointCount();
Shinya Kitaoka 120a6e
  for (i = 0; i < cpCount; i++)
Shinya Kitaoka 120a6e
    if (m_selection.isSelected(i))
Shinya Kitaoka 120a6e
      m_controlPointEditorStroke.moveControlPoint(i, delta);
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//---------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
void ControlPointEditorTool::moveSpeed(const TPointD &delta, bool isIn) {
Shinya Kitaoka 120a6e
  int i;
Shinya Kitaoka 120a6e
  for (i = 0; i < m_controlPointEditorStroke.getControlPointCount(); i++)
Shinya Kitaoka 120a6e
    if (m_selection.isSelected(i))
Shinya Kitaoka 120a6e
      m_controlPointEditorStroke.moveSpeed(i, delta, isIn, 4 * getPixelSize());
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//---------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
void ControlPointEditorTool::moveSegment(const TPointD &delta, bool dragging,
Shinya Kitaoka 120a6e
                                         bool isShiftPressed) {
Shinya Kitaoka 120a6e
  int beforeIndex = m_moveSegmentLimitation.first;
Shinya Kitaoka 120a6e
  int nextIndex   = m_moveSegmentLimitation.second;
Shinya Kitaoka 120a6e
  // Se e' premuto shift setto a cusp i due punti di controllo che delimitano il
Shinya Kitaoka 120a6e
  // segmento.
Shinya Kitaoka 120a6e
  if (isShiftPressed) {
Shinya Kitaoka 120a6e
    if (!m_controlPointEditorStroke.isCusp(beforeIndex)) {
Shinya Kitaoka 120a6e
      if (dragging)
Shinya Kitaoka 120a6e
        m_moveControlPointEditorStroke.setCusp(beforeIndex, true, false);
Shinya Kitaoka 120a6e
      else
Shinya Kitaoka 120a6e
        m_controlPointEditorStroke.setCusp(beforeIndex, true, false);
Shinya Kitaoka 120a6e
    }
Shinya Kitaoka 120a6e
    if (!m_controlPointEditorStroke.isCusp(nextIndex)) {
Shinya Kitaoka 120a6e
      if (dragging)
Shinya Kitaoka 120a6e
        m_moveControlPointEditorStroke.setCusp(nextIndex, true, true);
Shinya Kitaoka 120a6e
      else
Shinya Kitaoka 120a6e
        m_controlPointEditorStroke.setCusp(nextIndex, true, true);
Shinya Kitaoka 120a6e
    }
Shinya Kitaoka 120a6e
  }
Shinya Kitaoka 120a6e
  if (dragging)
Shinya Kitaoka 120a6e
    m_moveControlPointEditorStroke.moveSegment(beforeIndex, nextIndex, delta,
Shinya Kitaoka 120a6e
                                               m_pos);
Shinya Kitaoka 120a6e
  else
Shinya Kitaoka 120a6e
    m_controlPointEditorStroke.moveSegment(beforeIndex, nextIndex, delta,
Shinya Kitaoka 120a6e
                                           m_pos);
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//---------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
void ControlPointEditorTool::leftButtonDrag(const TPointD &pos,
Shinya Kitaoka 120a6e
                                            const TMouseEvent &e) {
Shinya Kitaoka 120a6e
  TVectorImageP vi(getImage(true));
Shinya Kitaoka 120a6e
  int currentStroke = m_controlPointEditorStroke.getStrokeIndex();
Shinya Kitaoka 120a6e
  if (!vi || currentStroke == -1 || m_action == NONE) return;
Shinya Kitaoka 120a6e
  QMutexLocker lock(vi->getMutex());
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  TPointD delta = pos - m_pos;
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  if (m_action == CP_MOVEMENT) {
Shinya Kitaoka 120a6e
    m_pos = pos;
Shinya Kitaoka 120a6e
    if (!m_selection.isSelected(m_lastPointSelected) && e.isCtrlPressed())
Shinya Kitaoka 120a6e
      m_selection.select(m_lastPointSelected);  // Controllo che non venga
Shinya Kitaoka 120a6e
                                                // deselezionata l'ultima
Shinya Kitaoka 120a6e
                                                // selezione nel movimento
Shinya Kitaoka 120a6e
    moveControlPoints(delta);
Shinya Kitaoka 120a6e
    m_isImageChanged = true;
Shinya Kitaoka 120a6e
  }
Shinya Kitaoka 120a6e
  if (m_action == SEGMENT_MOVEMENT) {
Shinya Kitaoka 120a6e
    m_moveControlPointEditorStroke = *m_controlPointEditorStroke.clone();
Shinya Kitaoka 120a6e
    moveSegment(delta, true, e.isShiftPressed());
Shinya Kitaoka 120a6e
    m_isImageChanged = true;
Shinya Kitaoka 120a6e
  }
Shinya Kitaoka 120a6e
  if (m_action == OUT_SPEED_MOVEMENT || m_action == IN_SPEED_MOVEMENT) {
Shinya Kitaoka 120a6e
    m_pos = pos;
Shinya Kitaoka 120a6e
    moveSpeed(delta, m_action == IN_SPEED_MOVEMENT);
Shinya Kitaoka 120a6e
    m_isImageChanged = true;
Shinya Kitaoka 120a6e
  }
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  if (m_action == RECT_SELECTION) {
Shinya Kitaoka 120a6e
    int cpCount        = m_controlPointEditorStroke.getControlPointCount();
Shinya Kitaoka 120a6e
    m_selectingRect.x0 = m_pos.x;
Shinya Kitaoka 120a6e
    m_selectingRect.y0 = m_pos.y;
Shinya Kitaoka 120a6e
    m_selectingRect.x1 = pos.x;
Shinya Kitaoka 120a6e
    m_selectingRect.y1 = pos.y;
Shinya Kitaoka 120a6e
    if (m_selectingRect.x0 > m_selectingRect.x1)
Shinya Kitaoka 120a6e
      tswap(m_selectingRect.x1, m_selectingRect.x0);
Shinya Kitaoka 120a6e
    if (m_selectingRect.y0 > m_selectingRect.y1)
Shinya Kitaoka 120a6e
      tswap(m_selectingRect.y1, m_selectingRect.y0);
Shinya Kitaoka 120a6e
    int i;
Shinya Kitaoka 120a6e
    m_selection.selectNone();
Shinya Kitaoka 120a6e
    for (i = 0; i < cpCount; i++)
Shinya Kitaoka 120a6e
      if (m_selectingRect.contains(
Shinya Kitaoka 120a6e
              m_controlPointEditorStroke.getControlPoint(i)))
Shinya Kitaoka 120a6e
        m_selection.select(i);
Shinya Kitaoka 120a6e
  }
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  invalidate();
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//---------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
void ControlPointEditorTool::leftButtonUp(const TPointD &pos,
Shinya Kitaoka 120a6e
                                          const TMouseEvent &e) {
Shinya Kitaoka 120a6e
  TVectorImageP vi(getImage(true));
Shinya Kitaoka 120a6e
  int currentStroke = m_controlPointEditorStroke.getStrokeIndex();
Shinya Kitaoka 120a6e
  if (!vi || currentStroke == -1) return;
Shinya Kitaoka 120a6e
  QMutexLocker lock(vi->getMutex());
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  if (m_action == EDIT_SEGMENT) {
Shinya Kitaoka 120a6e
    m_moveControlPointEditorStroke.setStroke((TVectorImage *)0, -1);
Shinya Kitaoka 120a6e
    TPointD delta = pos - m_pos;
Shinya Kitaoka 120a6e
    moveSegment(delta, false, e.isShiftPressed());
Shinya Kitaoka 120a6e
  }
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  if (m_action == RECT_SELECTION) {
Shinya Kitaoka 120a6e
    if (m_selection.isEmpty()) {
Shinya Kitaoka 120a6e
      // Non ho selezionato nulla
Shinya Kitaoka 120a6e
      if (!TTool::getApplication()
Shinya Kitaoka 120a6e
               ->getCurrentObject()
Shinya Kitaoka 120a6e
               ->isSpline())  // se non e' una spline deseleziono
Shinya Kitaoka 120a6e
        m_controlPointEditorStroke.setStroke((TVectorImage *)0, -1);
Shinya Kitaoka 120a6e
      m_action         = NONE;
Shinya Kitaoka 120a6e
      m_isImageChanged = false;
Shinya Kitaoka 120a6e
    } else {
Shinya Kitaoka 120a6e
      m_action = CP_MOVEMENT;
Shinya Kitaoka 120a6e
      m_selection.makeCurrent();
Shinya Kitaoka 120a6e
      m_isImageChanged = false;
Shinya Kitaoka 120a6e
    }
Shinya Kitaoka 120a6e
  }
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  if (m_action == NONE || !m_isImageChanged) {
Shinya Kitaoka 120a6e
    m_undo = 0;
Shinya Kitaoka 120a6e
    invalidate();
Shinya Kitaoka 120a6e
    return;
Shinya Kitaoka 120a6e
  }
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  notifyImageChanged();
Shinya Kitaoka 120a6e
  invalidate();
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  // Registro l'UNDO
Shinya Kitaoka 120a6e
  if (m_undo) {
Shinya Kitaoka 120a6e
    TUndoManager::manager()->add(m_undo);
Shinya Kitaoka 120a6e
    m_undo = 0;
Shinya Kitaoka 120a6e
  }
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//---------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
void ControlPointEditorTool::addContextMenuItems(QMenu *menu) {
Shinya Kitaoka 120a6e
  m_isMenuViewed = true;
Shinya Kitaoka 120a6e
  m_selection.addMenuItems(menu);
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//---------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
void ControlPointEditorTool::linkSpeedInOut(int index) {
Shinya Kitaoka 120a6e
  if ((index == 0 ||
Shinya Kitaoka 120a6e
       index == m_controlPointEditorStroke.getControlPointCount() - 1) &&
Shinya Kitaoka 120a6e
      !m_controlPointEditorStroke.isSelfLoop())
Shinya Kitaoka 120a6e
    return;
Shinya Kitaoka 120a6e
  if (m_action == IN_SPEED_MOVEMENT || m_action == CP_MOVEMENT)
Shinya Kitaoka 120a6e
    m_controlPointEditorStroke.setCusp(index, false, true);
Shinya Kitaoka 120a6e
  if (m_action == OUT_SPEED_MOVEMENT)
Shinya Kitaoka 120a6e
    m_controlPointEditorStroke.setCusp(index, false, false);
Shinya Kitaoka 120a6e
  invalidate();
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//---------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
void ControlPointEditorTool::unlinkSpeedInOut(int pointIndex) {
Shinya Kitaoka 120a6e
  m_controlPointEditorStroke.setCusp(pointIndex, true, true);
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//---------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
bool ControlPointEditorTool::keyDown(int key, TUINT32 flags,
Shinya Kitaoka 120a6e
                                     const TPoint &pos) {
Shinya Kitaoka 120a6e
  TVectorImageP vi(getImage(true));
Shinya Kitaoka 120a6e
  if (!vi || (vi && m_selection.isEmpty())) return false;
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  // Inizializzo l'UNDO
Shinya Kitaoka 120a6e
  initUndo();
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  TPointD delta;
Shinya Kitaoka 120a6e
  if (key == TwConsts::TK_UpArrow)
Shinya Kitaoka 120a6e
    delta.y = 1;
Shinya Kitaoka 120a6e
  else if (key == TwConsts::TK_DownArrow)
Shinya Kitaoka 120a6e
    delta.y = -1;
Shinya Kitaoka 120a6e
  else if (key == TwConsts::TK_LeftArrow)
Shinya Kitaoka 120a6e
    delta.x = -1;
Shinya Kitaoka 120a6e
  else if (key == TwConsts::TK_RightArrow)
Shinya Kitaoka 120a6e
    delta.x = 1;
Shinya Kitaoka 120a6e
  else
Shinya Kitaoka 120a6e
    return false;
Shinya Kitaoka 120a6e
  moveControlPoints(delta);
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  invalidate();
Shinya Kitaoka 120a6e
  // Registro l'UNDO
Shinya Kitaoka 120a6e
  TUndoManager::manager()->add(m_undo);
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  return true;
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//---------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
void ControlPointEditorTool::onEnter() {
Shinya Kitaoka 120a6e
  TVectorImageP vi(getImage(false));
Shinya Kitaoka 120a6e
  int currentStroke = m_controlPointEditorStroke.getStrokeIndex();
Shinya Kitaoka 120a6e
  if (m_isMenuViewed) {
Shinya Kitaoka 120a6e
    m_isMenuViewed = false;
Shinya Kitaoka 120a6e
    return;
Shinya Kitaoka 120a6e
  }
Shinya Kitaoka 120a6e
  /*m_draw=true;
Shinya Kitaoka 120a6e
  if(currentStroke==-1 || !vi)
Shinya Kitaoka 120a6e
          return;
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  m_controlPointEditorStroke.setStroke((TVectorImage*)0, -1);
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
if(TTool::getApplication()->getCurrentObject()->isSpline())
Shinya Kitaoka 120a6e
          m_controlPointEditorStroke.setStroke(vi, 0);*/
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//---------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
void ControlPointEditorTool::onLeave() {
Shinya Kitaoka 120a6e
  if (m_isMenuViewed) return;
Shinya Kitaoka 120a6e
  // m_draw=false;
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-----------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
bool ControlPointEditorTool::onPropertyChanged(std::string propertyName) {
Shinya Kitaoka 120a6e
  AutoSelectDrawing = (int)(m_autoSelectDrawing.getValue());
Shinya Kitaoka 120a6e
  return true;
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//---------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
void ControlPointEditorTool::onActivate() {
Shinya Kitaoka 120a6e
  // TODO: getApplication()->editImageOrSpline();
Shinya Kitaoka 120a6e
  m_autoSelectDrawing.setValue(AutoSelectDrawing ? 1 : 0);
Shinya Kitaoka 120a6e
  m_controlPointEditorStroke.setStroke((TVectorImage *)0, -1);
Shinya Kitaoka 120a6e
  m_draw = true;
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//---------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
void ControlPointEditorTool::onDeactivate() { m_draw = false; }
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//---------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
void ControlPointEditorTool::onImageChanged() {
Shinya Kitaoka 120a6e
  TVectorImageP vi(getImage(false));
Shinya Kitaoka 120a6e
  if (!vi) return;
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  int currentStroke = m_controlPointEditorStroke.getStrokeIndex();
Shinya Kitaoka 120a6e
  if (!vi || currentStroke == -1 ||
Shinya Kitaoka 120a6e
      m_controlPointEditorStroke.getControlPointCount() == 0 ||
Shinya Kitaoka 120a6e
      vi->getStrokeCount() == 0 || (int)vi->getStrokeCount() <= currentStroke) {
Shinya Kitaoka 120a6e
    m_controlPointEditorStroke.setStroke((TVectorImage *)0, -1);
Shinya Kitaoka 120a6e
    return;
Shinya Kitaoka 120a6e
  } else {
Shinya Kitaoka 120a6e
    m_selection.selectNone();
Shinya Kitaoka 120a6e
    m_controlPointEditorStroke.setStroke(vi, currentStroke);
Shinya Kitaoka 120a6e
  }
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//---------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
int ControlPointEditorTool::getCursorId() const {
Shinya Kitaoka 120a6e
  switch (m_cursorType) {
Shinya Kitaoka 120a6e
  case NORMAL:
Shinya Kitaoka 120a6e
    return ToolCursor::SplineEditorCursor;
Shinya Kitaoka 120a6e
  case ADD:
Shinya Kitaoka 120a6e
    return ToolCursor::SplineEditorCursorAdd;
Shinya Kitaoka 120a6e
  case EDIT_SPEED:
Shinya Kitaoka 120a6e
    return ToolCursor::SplineEditorCursorSelect;
Shinya Kitaoka 120a6e
  case EDIT_SEGMENT:
Shinya Kitaoka 120a6e
    return ToolCursor::PinchCursor;
Shinya Kitaoka 120a6e
  case NO_ACTIVE:
Shinya Kitaoka 120a6e
    return ToolCursor::CURSOR_NO;
Shinya Kitaoka 120a6e
  default:
Shinya Kitaoka 120a6e
    return ToolCursor::SplineEditorCursor;
Shinya Kitaoka 120a6e
  }
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
shun_iwasawa d51821
//-----------------------------------------------------------------------------
shun_iwasawa d51821
shun_iwasawa d51821
// returns true if the pressed key is recognized and processed in the tool
shun_iwasawa d51821
// instead of triggering the shortcut command.
shun_iwasawa d51821
bool ControlPointEditorTool::isEventAcceptable(QEvent *e) {
shun_iwasawa d51821
  if (!isEnabled()) return false;
shun_iwasawa d51821
  TVectorImageP vi(getImage(false));
shun_iwasawa d51821
  if (!vi || (vi && m_selection.isEmpty())) return false;
shun_iwasawa d51821
  // arrow keys will be used for moving the selected points
shun_iwasawa d51821
  QKeyEvent *keyEvent = static_cast<qkeyevent *="">(e);</qkeyevent>
shun_iwasawa d51821
  // shift + arrow will not be recognized for now
shun_iwasawa d51821
  if (keyEvent->modifiers() & Qt::ShiftModifier) return false;
shun_iwasawa d51821
  int key = keyEvent->key();
shun_iwasawa d51821
  return (key == Qt::Key_Up || key == Qt::Key_Down || key == Qt::Key_Left ||
shun_iwasawa d51821
          key == Qt::Key_Right);
shun_iwasawa d51821
}
shun_iwasawa d51821
Toshihiro Shimizu 890ddd
//=============================================================================
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
// TTool *getSplineEditorTool() {return &controlPointEditorTool;}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//=============================================================================