/*
* Copyright (C) 2014 Alfons Wirtz
* website www.freerouting.net
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License at <http://www.gnu.org/licenses/>
* for more details.
*
* DragItemState.java
*
* Created on 9. November 2003, 08:13
*/
package interactive;
import java.util.Collection;
import java.util.Set;
import java.util.TreeSet;
import java.util.Iterator;
import geometry.planar.FloatPoint;
import geometry.planar.IntPoint;
import geometry.planar.Vector;
import board.AngleRestriction;
import board.Item;
import board.MoveComponent;
/**
* Class for interactive dragging items with the mouse on a routing board
*
* @author Alfons Wirtz
*/
public class DragItemState extends DragState
{
/** Creates a new instance of MoveItemState */
protected DragItemState(Item p_item_to_move, FloatPoint p_location, InteractiveState p_parent_state, BoardHandling p_board_handling, Logfile p_logfile)
{
super(p_location, p_parent_state, p_board_handling, p_logfile);
item_to_move = p_item_to_move;
}
public void display_default_message()
{
hdlg.screen_messages.set_status_message(resources.getString("dragging_item"));
}
/**
* Moves the items of the group to p_to_location.
* Return this.return_state, if an error eccured while moving,
* so that an undo may be necessary.
*/
public InteractiveState move_to(FloatPoint p_to_location)
{
IntPoint to_location = p_to_location.round();
IntPoint from_location = this.previous_location.round();
if (hdlg.get_routing_board().rules.get_trace_angle_restriction() == AngleRestriction.NINETY_DEGREE)
{
to_location = to_location.orthogonal_projection(from_location);
}
else if (hdlg.get_routing_board().rules.get_trace_angle_restriction() == AngleRestriction.FORTYFIVE_DEGREE)
{
to_location = to_location.fortyfive_degree_projection(from_location);
}
if (to_location.equals(from_location))
{
return this;
}
if (item_to_move.is_user_fixed())
{
hdlg.screen_messages.set_status_message("Please unfix item before dragging");
return this;
}
MoveComponent move_component = null;
Vector rel_coor = to_location.difference_by(from_location);
double length = rel_coor.length_approx();
boolean shove_ok = false;
for (int i = 0; i < 2; ++i)
{
move_component = new MoveComponent(item_to_move, rel_coor, 99, 5);
if (move_component.check())
{
shove_ok = true;
break;
}
if (i == 0)
{
// reduce evtl. the shove distance to make the check shove function
// work properly, if more than 1 trace have to be shoved.
double sample_width = 2 * hdlg.get_routing_board().get_min_trace_half_width();
if (length > sample_width)
{
rel_coor = rel_coor.change_length_approx(sample_width);
}
}
}
if (shove_ok)
{
if (!this.something_dragged)
{
// initialisitions for the first time dragging
this.observers_activated = !hdlg.get_routing_board().observers_active();
if (this.observers_activated)
{
hdlg.get_routing_board().start_notify_observers();
}
// make the situation restorable by undo
hdlg.get_routing_board().generate_snapshot();
if (logfile != null)
{
// Delayed till here because otherwise the mouse
// might have been only clicked for selecting
// and not pressed for moving.
logfile.start_scope(LogfileScope.DRAGGING_ITEMS, this.previous_location);
}
this.something_dragged = true;
}
if (!move_component.insert(hdlg.settings.trace_pull_tight_region_width,
hdlg.settings.trace_pull_tight_accuracy))
{
// an insert error occured, end the drag state
return this.return_state;
}
hdlg.repaint();
}
this.previous_location = p_to_location;//(IntPoint)this.curr_location.translate_by(rel_coor);
return this;
}
public InteractiveState button_released()
{
if (this.observers_activated)
{
hdlg.get_routing_board().end_notify_observers();
this.observers_activated = false;
}
if (logfile != null && something_dragged)
{
logfile.start_scope(LogfileScope.COMPLETE_SCOPE);
}
if (something_dragged)
{
// Update the incompletes for the nets of the moved items.
if (item_to_move.get_component_no() == 0)
{
for (int i = 0; i < item_to_move.net_count(); ++i)
{
hdlg.update_ratsnest(item_to_move.get_net_no(i));
}
}
else
{
Collection<Item> moved_items = hdlg.get_routing_board().get_component_items(item_to_move.get_component_no());
Set<Integer> changed_nets = new TreeSet<Integer>();
Iterator<Item> it = moved_items.iterator();
while (it.hasNext())
{
Item curr_moved_item = it.next();
for (int i = 0; i < curr_moved_item.net_count(); ++i)
{
changed_nets.add(new Integer(curr_moved_item.get_net_no(i)));
}
}
for (Integer curr_net_no : changed_nets)
{
hdlg.update_ratsnest(curr_net_no.intValue());
}
}
}
else
{
hdlg.show_ratsnest();
}
hdlg.screen_messages.set_status_message("");
return this.return_state;
}
private Item item_to_move = null;
}