<commit_before>/*=========================================================================

 Program:   openCherry Platform
 Language:  C++
 Date:      $Date$
 Version:   $Revision$

 Copyright (c) German Cancer Research Center, Division of Medical and
 Biological Informatics. All rights reserved.
 See MITKCopyright.txt or http://www.mitk.org/copyright.html for details.

 This software is distributed WITHOUT ANY WARRANTY; without even
 the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
 PURPOSE.  See the above copyright notices for more information.

 =========================================================================*/

#include "cherryDragUtil.h"

#include "../cherryGeometry.h"
#include "../tweaklets/cherryGuiWidgetsTweaklet.h"
#include "../tweaklets/cherryDnDTweaklet.h"
#include "../tweaklets/cherryITracker.h"

namespace cherry
{

const std::string DragUtil::DROP_TARGET_ID =
    "org.opencherry.ui.internal.dropTarget";

TestDropLocation::Pointer DragUtil::forcedDropTarget(0);

std::list<IDragOverListener::Pointer> DragUtil::defaultTargets = std::list<
    IDragOverListener::Pointer>();

DragUtil::TrackerMoveListener::TrackerMoveListener(Object::Pointer draggedItem,
    const Rectangle& sourceBounds, const Point& initialLocation,
    bool allowSnapping) :
  allowSnapping(allowSnapping), draggedItem(draggedItem), sourceBounds(
      sourceBounds), initialLocation(initialLocation)
{

}

GuiTk::IControlListener::Events::Types DragUtil::TrackerMoveListener::GetEventTypes() const
{
  return Events::MOVED;
}

void DragUtil::TrackerMoveListener::ControlMoved(
    GuiTk::ControlEvent::Pointer event)
{

  // Get the curslor location as a point
  Point location(event->x, event->y);

  // Select a drop target; use the global one by default
  IDropTarget::Pointer target;

  void* targetControl =
      Tweaklets::Get(GuiWidgetsTweaklet::KEY)->GetCursorControl();

  // Get the ITracker which fired the event
  ITracker* tracker = static_cast<ITracker*> (event->item);

  // Get the drop target for this location
  target = DragUtil::GetDropTarget(targetControl, draggedItem, location,
      tracker->GetRectangle());

  // Set up the tracker feedback based on the target
  Rectangle snapTarget;
  if (target != 0)
  {
    snapTarget = target->GetSnapRectangle();

    tracker->SetCursor(target->GetCursor());
  }
  else
  {
    tracker->SetCursor(DnDTweaklet::CURSOR_INVALID);
  }

  // If snapping then reset the tracker's rectangle based on the current drop target
  if (allowSnapping)
  {
    if (snapTarget.width == 0 || snapTarget.height == 0)
    {
      snapTarget = Rectangle(sourceBounds.x + location.x - initialLocation.x,
          sourceBounds.y + location.y - initialLocation.y, sourceBounds.width,
          sourceBounds.height);
    }

    // Try to prevent flicker: don't change the rectangles if they're already in
    // the right location
    Rectangle currentRectangle = tracker->GetRectangle();

    if (!(currentRectangle == snapTarget))
    {
      tracker->SetRectangle(snapTarget);
    }
  }

}

DragUtil::TargetListType::Pointer DragUtil::GetTargetList(void* control)
{
  Object::Pointer data = Tweaklets::Get(GuiWidgetsTweaklet::KEY)->GetData(
      control, DROP_TARGET_ID);
  TargetListType::Pointer list = data.Cast<TargetListType> ();
  return list;
}

IDropTarget::Pointer DragUtil::GetDropTarget(const std::list<
    IDragOverListener::Pointer>& toSearch, void* mostSpecificControl,
    Object::Pointer draggedObject, const Point& position,
    const Rectangle& dragRectangle)
{

  for (std::list<IDragOverListener::Pointer>::const_iterator iter =
      toSearch.begin(); iter != toSearch.end(); ++iter)
  {
    IDragOverListener::Pointer next = *iter;

    IDropTarget::Pointer dropTarget = next->Drag(mostSpecificControl,
        draggedObject, position, dragRectangle);

    if (dropTarget != 0)
    {
      return dropTarget;
    }
  }

  return IDropTarget::Pointer(0);
}

void DragUtil::AddDragTarget(void* control, IDragOverListener::Pointer target)
{
  if (control == 0)
  {
    defaultTargets.push_back(target);
  }
  else
  {
    TargetListType::Pointer targetList = GetTargetList(control);

    if (targetList == 0)
    {
      targetList = new TargetListType();
      Tweaklets::Get(GuiWidgetsTweaklet::KEY)->SetData(control, DROP_TARGET_ID,
          targetList);
    }
    targetList->push_back(target);
  }
}

void DragUtil::RemoveDragTarget(void* control,
    IDragOverListener::Pointer target)
{
  if (control == 0)
  {
    defaultTargets.push_back(target);
  }
  else
  {
    TargetListType::Pointer targetList = GetTargetList(control);
    if (targetList != 0)
    {
      targetList->remove(target);
      if (targetList->empty())
      {<commit_msg>FIX (#2716): changing to another perspective and detaching a part crashed due to not removed the default drag target. fixed by removing the target instead of adding it again.<commit_after>/*=========================================================================

 Program:   openCherry Platform
 Language:  C++
 Date:      $Date$
 Version:   $Revision$

 Copyright (c) German Cancer Research Center, Division of Medical and
 Biological Informatics. All rights reserved.
 See MITKCopyright.txt or http://www.mitk.org/copyright.html for details.

 This software is distributed WITHOUT ANY WARRANTY; without even
 the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
 PURPOSE.  See the above copyright notices for more information.

 =========================================================================*/

#include "cherryDragUtil.h"

#include "../cherryGeometry.h"
#include "../tweaklets/cherryGuiWidgetsTweaklet.h"
#include "../tweaklets/cherryDnDTweaklet.h"
#include "../tweaklets/cherryITracker.h"

namespace cherry
{

const std::string DragUtil::DROP_TARGET_ID =
    "org.opencherry.ui.internal.dropTarget";

TestDropLocation::Pointer DragUtil::forcedDropTarget(0);

std::list<IDragOverListener::Pointer> DragUtil::defaultTargets = std::list<
    IDragOverListener::Pointer>();

DragUtil::TrackerMoveListener::TrackerMoveListener(Object::Pointer draggedItem,
    const Rectangle& sourceBounds, const Point& initialLocation,
    bool allowSnapping) :
  allowSnapping(allowSnapping), draggedItem(draggedItem), sourceBounds(
      sourceBounds), initialLocation(initialLocation)
{

}

GuiTk::IControlListener::Events::Types DragUtil::TrackerMoveListener::GetEventTypes() const
{
  return Events::MOVED;
}

void DragUtil::TrackerMoveListener::ControlMoved(
    GuiTk::ControlEvent::Pointer event)
{

  // Get the curslor location as a point
  Point location(event->x, event->y);

  // Select a drop target; use the global one by default
  IDropTarget::Pointer target;

  void* targetControl =
      Tweaklets::Get(GuiWidgetsTweaklet::KEY)->GetCursorControl();

  // Get the ITracker which fired the event
  ITracker* tracker = static_cast<ITracker*> (event->item);

  // Get the drop target for this location
  target = DragUtil::GetDropTarget(targetControl, draggedItem, location,
      tracker->GetRectangle());

  // Set up the tracker feedback based on the target
  Rectangle snapTarget;
  if (target != 0)
  {
    snapTarget = target->GetSnapRectangle();

    tracker->SetCursor(target->GetCursor());
  }
  else
  {
    tracker->SetCursor(DnDTweaklet::CURSOR_INVALID);
  }

  // If snapping then reset the tracker's rectangle based on the current drop target
  if (allowSnapping)
  {
    if (snapTarget.width == 0 || snapTarget.height == 0)
    {
      snapTarget = Rectangle(sourceBounds.x + location.x - initialLocation.x,
          sourceBounds.y + location.y - initialLocation.y, sourceBounds.width,
          sourceBounds.height);
    }

    // Try to prevent flicker: don't change the rectangles if they're already in
    // the right location
    Rectangle currentRectangle = tracker->GetRectangle();

    if (!(currentRectangle == snapTarget))
    {
      tracker->SetRectangle(snapTarget);
    }
  }

}

DragUtil::TargetListType::Pointer DragUtil::GetTargetList(void* control)
{
  Object::Pointer data = Tweaklets::Get(GuiWidgetsTweaklet::KEY)->GetData(
      control, DROP_TARGET_ID);
  TargetListType::Pointer list = data.Cast<TargetListType> ();
  return list;
}

IDropTarget::Pointer DragUtil::GetDropTarget(const std::list<
    IDragOverListener::Pointer>& toSearch, void* mostSpecificControl,
    Object::Pointer draggedObject, const Point& position,
    const Rectangle& dragRectangle)
{

  for (std::list<IDragOverListener::Pointer>::const_iterator iter =
      toSearch.begin(); iter != toSearch.end(); ++iter)
  {
    IDragOverListener::Pointer next = *iter;

    IDropTarget::Pointer dropTarget = next->Drag(mostSpecificControl,
        draggedObject, position, dragRectangle);

    if (dropTarget != 0)
    {
      return dropTarget;
    }
  }

  return IDropTarget::Pointer(0);
}

void DragUtil::AddDragTarget(void* control, IDragOverListener::Pointer target)
{
  if (control == 0)
  {
    defaultTargets.push_back(target);
  }
  else
  {
    TargetListType::Pointer targetList = GetTargetList(control);

    if (targetList == 0)
    {
      targetList = new TargetListType();
      Tweaklets::Get(GuiWidgetsTweaklet::KEY)->SetData(control, DROP_TARGET_ID,
          targetList);
    }
    targetList->push_back(target);
  }
}

void DragUtil::RemoveDragTarget(void* control,
    IDragOverListener::Pointer target)
{
  if (control == 0)
  {
    defaultTargets.remove(target);
  }
  else
  {
    TargetListType::Pointer targetList = GetTargetList(control);
    if (targetList != 0)
    {
      targetList->remove(target);
      if (targetList->empty())
      {
{'fraction_non_alphanumeric': 0.1404890178201409, 'fraction_numerical': 0.0024865312888520514, 'mean_word_length': 4.377715877437326, 'pattern_counts': {'":': 0, '<': 15, '<?xml version=': 0, '>': 49, 'https://': 0, 'lorem ipsum': 0, 'www.': 2, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '6648155', 'n_tokens_mistral': 2857, 'n_tokens_neox': 2753, 'n_words': 660}