Merge pull request #437 from KLayout/issue-436

Issue 436 (enhancement of "interactive move", "copy", "interactive duplicate")
This commit is contained in:
Matthias Köfferlein 2019-12-08 09:12:58 +01:00 committed by GitHub
commit afbb3832e6
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
21 changed files with 476 additions and 202 deletions

View File

@ -901,11 +901,6 @@ Service::drag_cancel ()
delete mp_active_ruler; delete mp_active_ruler;
mp_active_ruler = 0; mp_active_ruler = 0;
} }
if (mp_transient_ruler) {
delete mp_transient_ruler;
mp_transient_ruler = 0;
}
} }
int int
@ -1030,6 +1025,8 @@ Service::begin_move (lay::Editable::MoveMode mode, const db::DPoint &p, lay::ang
// cancel any pending move or drag operations, reset mp_active_ruler // cancel any pending move or drag operations, reset mp_active_ruler
widget ()->drag_cancel (); // KLUDGE: every service does this to the same service manager widget ()->drag_cancel (); // KLUDGE: every service does this to the same service manager
clear_transient_selection ();
// choose move mode // choose move mode
if (mode == lay::Editable::Selected) { if (mode == lay::Editable::Selected) {
@ -1486,6 +1483,7 @@ Service::mouse_click_event (const db::DPoint &p, unsigned int buttons, bool prio
// stop dragging // stop dragging
drag_cancel (); drag_cancel ();
clear_transient_selection ();
// end the transaction // end the transaction
manager ()->commit (); manager ()->commit ();
@ -1535,6 +1533,7 @@ void
Service::deactivated () Service::deactivated ()
{ {
drag_cancel (); drag_cancel ();
clear_transient_selection ();
} }
std::pair<bool, db::DPoint> std::pair<bool, db::DPoint>
@ -1576,6 +1575,8 @@ struct RulerIdComp
void void
Service::reduce_rulers (int num) Service::reduce_rulers (int num)
{ {
clear_transient_selection ();
lay::AnnotationShapes::iterator rfrom = mp_view->annotation_shapes ().begin (); lay::AnnotationShapes::iterator rfrom = mp_view->annotation_shapes ().begin ();
lay::AnnotationShapes::iterator rto = mp_view->annotation_shapes ().end (); lay::AnnotationShapes::iterator rto = mp_view->annotation_shapes ().end ();
@ -1921,6 +1922,21 @@ Service::clear_transient_selection ()
} }
} }
void
Service::transient_to_selection ()
{
if (mp_transient_ruler) {
for (lay::AnnotationShapes::iterator r = mp_view->annotation_shapes ().begin (); r != mp_view->annotation_shapes ().end (); ++r) {
const ant::Object *robj = dynamic_cast <const ant::Object *> (r->ptr ());
if (robj == mp_transient_ruler->ruler ()) {
m_selected.insert (std::make_pair (r, 0));
selection_to_view ();
return;
}
}
}
}
void void
Service::clear_previous_selection () Service::clear_previous_selection ()
{ {

View File

@ -284,6 +284,11 @@ public:
*/ */
virtual void clear_previous_selection (); virtual void clear_previous_selection ();
/**
* @brief Turns the transient selection to the selection
*/
virtual void transient_to_selection ();
/** /**
* @brief Establish a transient selection * @brief Establish a transient selection
*/ */
@ -548,7 +553,7 @@ private:
bool select (obj_iterator obj, lay::Editable::SelectionMode mode); bool select (obj_iterator obj, lay::Editable::SelectionMode mode);
/** /**
* @brief Clear the selection * @brief Clears the selection
*/ */
void clear_selection (); void clear_selection ();

View File

@ -1,7 +1,8 @@
<ui version="4.0" > <?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>CopyModeDialog</class> <class>CopyModeDialog</class>
<widget class="QDialog" name="CopyModeDialog" > <widget class="QDialog" name="CopyModeDialog">
<property name="geometry" > <property name="geometry">
<rect> <rect>
<x>0</x> <x>0</x>
<y>0</y> <y>0</y>
@ -9,38 +10,56 @@
<height>164</height> <height>164</height>
</rect> </rect>
</property> </property>
<property name="windowTitle" > <property name="windowTitle">
<string>Copy Options</string> <string>Copy Options</string>
</property> </property>
<layout class="QVBoxLayout" > <layout class="QVBoxLayout">
<property name="margin" > <property name="spacing">
<number>9</number>
</property>
<property name="spacing" >
<number>6</number> <number>6</number>
</property> </property>
<property name="leftMargin">
<number>9</number>
</property>
<property name="topMargin">
<number>9</number>
</property>
<property name="rightMargin">
<number>9</number>
</property>
<property name="bottomMargin">
<number>9</number>
</property>
<item> <item>
<widget class="QGroupBox" name="groupBox" > <widget class="QGroupBox" name="groupBox">
<property name="title" > <property name="title">
<string>Copy Mode</string> <string>Copy Mode</string>
</property> </property>
<layout class="QVBoxLayout" > <layout class="QVBoxLayout">
<property name="margin" > <property name="spacing">
<number>9</number>
</property>
<property name="spacing" >
<number>6</number> <number>6</number>
</property> </property>
<property name="leftMargin">
<number>9</number>
</property>
<property name="topMargin">
<number>9</number>
</property>
<property name="rightMargin">
<number>9</number>
</property>
<property name="bottomMargin">
<number>9</number>
</property>
<item> <item>
<widget class="QRadioButton" name="shallow_rb" > <widget class="QRadioButton" name="shallow_rb">
<property name="text" > <property name="text">
<string>Shallow copy (instances only)</string> <string>Shallow copy (instances only)</string>
</property> </property>
</widget> </widget>
</item> </item>
<item> <item>
<widget class="QRadioButton" name="deep_rb" > <widget class="QRadioButton" name="deep_rb">
<property name="text" > <property name="text">
<string>Deep copy (instances plus cell)</string> <string>Deep copy (instances plus cell)</string>
</property> </property>
</widget> </widget>
@ -48,12 +67,19 @@
</layout> </layout>
</widget> </widget>
</item> </item>
<item>
<widget class="QCheckBox" name="dont_ask_cbx">
<property name="text">
<string>Don't ask again (you can always reset this in the editor options)</string>
</property>
</widget>
</item>
<item> <item>
<spacer> <spacer>
<property name="orientation" > <property name="orientation">
<enum>Qt::Vertical</enum> <enum>Qt::Vertical</enum>
</property> </property>
<property name="sizeHint" > <property name="sizeHint" stdset="0">
<size> <size>
<width>20</width> <width>20</width>
<height>40</height> <height>40</height>
@ -62,12 +88,12 @@
</spacer> </spacer>
</item> </item>
<item> <item>
<widget class="QDialogButtonBox" name="buttonBox" > <widget class="QDialogButtonBox" name="buttonBox">
<property name="orientation" > <property name="orientation">
<enum>Qt::Horizontal</enum> <enum>Qt::Horizontal</enum>
</property> </property>
<property name="standardButtons" > <property name="standardButtons">
<set>QDialogButtonBox::Cancel|QDialogButtonBox::NoButton|QDialogButtonBox::Ok</set> <set>QDialogButtonBox::Cancel|QDialogButtonBox::Ok</set>
</property> </property>
</widget> </widget>
</item> </item>
@ -81,11 +107,11 @@
<receiver>CopyModeDialog</receiver> <receiver>CopyModeDialog</receiver>
<slot>accept()</slot> <slot>accept()</slot>
<hints> <hints>
<hint type="sourcelabel" > <hint type="sourcelabel">
<x>248</x> <x>248</x>
<y>254</y> <y>254</y>
</hint> </hint>
<hint type="destinationlabel" > <hint type="destinationlabel">
<x>157</x> <x>157</x>
<y>274</y> <y>274</y>
</hint> </hint>
@ -97,11 +123,11 @@
<receiver>CopyModeDialog</receiver> <receiver>CopyModeDialog</receiver>
<slot>reject()</slot> <slot>reject()</slot>
<hints> <hints>
<hint type="sourcelabel" > <hint type="sourcelabel">
<x>316</x> <x>316</x>
<y>260</y> <y>260</y>
</hint> </hint>
<hint type="destinationlabel" > <hint type="destinationlabel">
<x>286</x> <x>286</x>
<y>274</y> <y>274</y>
</hint> </hint>

View File

@ -1,7 +1,8 @@
<ui version="4.0" > <?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>EditorOptionsGeneric</class> <class>EditorOptionsGeneric</class>
<widget class="QWidget" name="EditorOptionsGeneric" > <widget class="QWidget" name="EditorOptionsGeneric">
<property name="geometry" > <property name="geometry">
<rect> <rect>
<x>0</x> <x>0</x>
<y>0</y> <y>0</y>
@ -9,34 +10,52 @@
<height>417</height> <height>417</height>
</rect> </rect>
</property> </property>
<property name="windowTitle" > <property name="windowTitle">
<string>Form</string> <string>Form</string>
</property> </property>
<layout class="QVBoxLayout" > <layout class="QVBoxLayout">
<property name="margin" > <property name="spacing">
<number>6</number>
</property>
<property name="leftMargin">
<number>9</number> <number>9</number>
</property> </property>
<property name="spacing" > <property name="topMargin">
<number>6</number> <number>9</number>
</property>
<property name="rightMargin">
<number>9</number>
</property>
<property name="bottomMargin">
<number>9</number>
</property> </property>
<item> <item>
<widget class="QGroupBox" name="groupBox" > <widget class="QGroupBox" name="groupBox">
<property name="title" > <property name="title">
<string>Snapping</string> <string>Snapping</string>
</property> </property>
<layout class="QGridLayout" > <layout class="QGridLayout">
<property name="margin" > <property name="leftMargin">
<number>9</number> <number>9</number>
</property> </property>
<property name="spacing" > <property name="topMargin">
<number>9</number>
</property>
<property name="rightMargin">
<number>9</number>
</property>
<property name="bottomMargin">
<number>9</number>
</property>
<property name="spacing">
<number>6</number> <number>6</number>
</property> </property>
<item row="0" column="4" > <item row="0" column="4">
<spacer> <spacer>
<property name="orientation" > <property name="orientation">
<enum>Qt::Horizontal</enum> <enum>Qt::Horizontal</enum>
</property> </property>
<property name="sizeHint" > <property name="sizeHint" stdset="0">
<size> <size>
<width>148</width> <width>148</width>
<height>16</height> <height>16</height>
@ -44,15 +63,15 @@
</property> </property>
</spacer> </spacer>
</item> </item>
<item row="0" column="2" > <item row="0" column="2">
<spacer> <spacer>
<property name="orientation" > <property name="orientation">
<enum>Qt::Horizontal</enum> <enum>Qt::Horizontal</enum>
</property> </property>
<property name="sizeType" > <property name="sizeType">
<enum>QSizePolicy::Fixed</enum> <enum>QSizePolicy::Fixed</enum>
</property> </property>
<property name="sizeHint" > <property name="sizeHint" stdset="0">
<size> <size>
<width>16</width> <width>16</width>
<height>20</height> <height>20</height>
@ -60,57 +79,55 @@
</property> </property>
</spacer> </spacer>
</item> </item>
<item row="0" column="3" > <item row="0" column="3">
<widget class="QLineEdit" name="edit_grid_le" > <widget class="QLineEdit" name="edit_grid_le">
<property name="sizePolicy" > <property name="sizePolicy">
<sizepolicy> <sizepolicy hsizetype="Fixed" vsizetype="Fixed">
<hsizetype>0</hsizetype>
<vsizetype>0</vsizetype>
<horstretch>0</horstretch> <horstretch>0</horstretch>
<verstretch>0</verstretch> <verstretch>0</verstretch>
</sizepolicy> </sizepolicy>
</property> </property>
<property name="toolTip" > <property name="toolTip">
<string>Enter the grid in micron. Can be anisotropic ("gx,gy")</string> <string>Enter the grid in micron. Can be anisotropic (&quot;gx,gy&quot;)</string>
</property> </property>
</widget> </widget>
</item> </item>
<item row="0" column="0" > <item row="0" column="0">
<widget class="QLabel" name="label_5" > <widget class="QLabel" name="label_5">
<property name="text" > <property name="text">
<string>Grid</string> <string>Grid</string>
</property> </property>
</widget> </widget>
</item> </item>
<item row="1" column="0" > <item row="1" column="0">
<widget class="QLabel" name="label_6" > <widget class="QLabel" name="label_6">
<property name="text" > <property name="text">
<string>Objects </string> <string>Objects </string>
</property> </property>
</widget> </widget>
</item> </item>
<item row="0" column="1" > <item row="0" column="1">
<widget class="QComboBox" name="grid_cb" > <widget class="QComboBox" name="grid_cb">
<item> <item>
<property name="text" > <property name="text">
<string>No grid</string> <string>No grid</string>
</property> </property>
</item> </item>
<item> <item>
<property name="text" > <property name="text">
<string>Global grid</string> <string>Global grid</string>
</property> </property>
</item> </item>
<item> <item>
<property name="text" > <property name="text">
<string>Other grid ...</string> <string>Other grid ...</string>
</property> </property>
</item> </item>
</widget> </widget>
</item> </item>
<item row="1" column="1" colspan="4" > <item row="1" column="1" colspan="4">
<widget class="QCheckBox" name="snap_objects_cbx" > <widget class="QCheckBox" name="snap_objects_cbx">
<property name="text" > <property name="text">
<string>Snap to other objects</string> <string>Snap to other objects</string>
</property> </property>
</widget> </widget>
@ -119,75 +136,84 @@
</widget> </widget>
</item> </item>
<item> <item>
<widget class="QGroupBox" name="groupBox_2" > <widget class="QGroupBox" name="groupBox_2">
<property name="title" > <property name="title">
<string>Angle Constraints</string> <string>Angle Constraints</string>
</property> </property>
<layout class="QGridLayout" > <layout class="QGridLayout">
<property name="margin" > <property name="leftMargin">
<number>9</number> <number>9</number>
</property> </property>
<property name="spacing" > <property name="topMargin">
<number>9</number>
</property>
<property name="rightMargin">
<number>9</number>
</property>
<property name="bottomMargin">
<number>9</number>
</property>
<property name="spacing">
<number>6</number> <number>6</number>
</property> </property>
<item row="1" column="0" > <item row="1" column="0">
<widget class="QLabel" name="label_3" > <widget class="QLabel" name="label_3">
<property name="text" > <property name="text">
<string>Movements </string> <string>Movements </string>
</property> </property>
</widget> </widget>
</item> </item>
<item row="0" column="0" > <item row="0" column="0">
<widget class="QLabel" name="label_2" > <widget class="QLabel" name="label_2">
<property name="text" > <property name="text">
<string>Connections </string> <string>Connections </string>
</property> </property>
</widget> </widget>
</item> </item>
<item row="0" column="1" > <item row="0" column="1">
<widget class="QComboBox" name="conn_angle_cb" > <widget class="QComboBox" name="conn_angle_cb">
<item> <item>
<property name="text" > <property name="text">
<string>Any Angle</string> <string>Any Angle</string>
</property> </property>
</item> </item>
<item> <item>
<property name="text" > <property name="text">
<string>Diagonal</string> <string>Diagonal</string>
</property> </property>
</item> </item>
<item> <item>
<property name="text" > <property name="text">
<string>Manhattan</string> <string>Manhattan</string>
</property> </property>
</item> </item>
</widget> </widget>
</item> </item>
<item row="1" column="1" > <item row="1" column="1">
<widget class="QComboBox" name="move_angle_cb" > <widget class="QComboBox" name="move_angle_cb">
<item> <item>
<property name="text" > <property name="text">
<string>Any Direction</string> <string>Any Direction</string>
</property> </property>
</item> </item>
<item> <item>
<property name="text" > <property name="text">
<string>Diagonal</string> <string>Diagonal</string>
</property> </property>
</item> </item>
<item> <item>
<property name="text" > <property name="text">
<string>Manhattan</string> <string>Manhattan</string>
</property> </property>
</item> </item>
</widget> </widget>
</item> </item>
<item rowspan="2" row="0" column="2" > <item row="0" column="2" rowspan="2">
<spacer> <spacer>
<property name="orientation" > <property name="orientation">
<enum>Qt::Horizontal</enum> <enum>Qt::Horizontal</enum>
</property> </property>
<property name="sizeHint" > <property name="sizeHint" stdset="0">
<size> <size>
<width>257</width> <width>257</width>
<height>41</height> <height>41</height>
@ -199,36 +225,91 @@
</widget> </widget>
</item> </item>
<item> <item>
<widget class="QGroupBox" name="groupBox_3" > <widget class="QGroupBox" name="groupBox_3">
<property name="title" > <property name="title">
<string>Selection Mode</string> <string>Hierarchical Features</string>
</property> </property>
<layout class="QGridLayout" > <layout class="QGridLayout">
<property name="margin" > <property name="leftMargin">
<number>9</number> <number>9</number>
</property> </property>
<property name="spacing" > <property name="topMargin">
<number>9</number>
</property>
<property name="rightMargin">
<number>9</number>
</property>
<property name="bottomMargin">
<number>9</number>
</property>
<property name="spacing">
<number>6</number> <number>6</number>
</property> </property>
<item row="0" column="1" > <item row="1" column="0">
<widget class="QCheckBox" name="hier_sel_cbx" > <widget class="QLabel" name="label">
<property name="sizePolicy" > <property name="text">
<sizepolicy> <string>Copy mode</string>
<hsizetype>7</hsizetype> </property>
<vsizetype>0</vsizetype> </widget>
</item>
<item row="0" column="0">
<widget class="QLabel" name="label_4">
<property name="text">
<string>Shallow select</string>
</property>
</widget>
</item>
<item row="1" column="1" colspan="2">
<widget class="QComboBox" name="hier_copy_mode_cbx">
<property name="sizePolicy">
<sizepolicy hsizetype="Preferred" vsizetype="Fixed">
<horstretch>0</horstretch> <horstretch>0</horstretch>
<verstretch>0</verstretch> <verstretch>0</verstretch>
</sizepolicy> </sizepolicy>
</property> </property>
<property name="text" > <property name="sizeAdjustPolicy">
<string>Select top level objects only</string> <enum>QComboBox::AdjustToContentsOnFirstShow</enum>
</property> </property>
<item>
<property name="text">
<string>Shallow mode (instance only)</string>
</property>
</item>
<item>
<property name="text">
<string>Deep mode (instance and cell)</string>
</property>
</item>
<item>
<property name="text">
<string>Ask</string>
</property>
</item>
</widget> </widget>
</item> </item>
<item row="0" column="0" > <item row="1" column="3">
<widget class="QLabel" name="label_4" > <spacer name="horizontalSpacer">
<property name="text" > <property name="orientation">
<string>Hierarchy </string> <enum>Qt::Horizontal</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>40</width>
<height>20</height>
</size>
</property>
</spacer>
</item>
<item row="0" column="1" colspan="3">
<widget class="QCheckBox" name="hier_sel_cbx">
<property name="sizePolicy">
<sizepolicy hsizetype="Expanding" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="text">
<string>Select top level objects only</string>
</property> </property>
</widget> </widget>
</item> </item>
@ -236,30 +317,37 @@
</widget> </widget>
</item> </item>
<item> <item>
<widget class="QGroupBox" name="groupBox_4" > <widget class="QGroupBox" name="groupBox_4">
<property name="title" > <property name="title">
<string>Instance Display</string> <string>Instance Display</string>
</property> </property>
<layout class="QHBoxLayout" > <layout class="QHBoxLayout">
<property name="margin" > <property name="spacing">
<number>9</number>
</property>
<property name="spacing" >
<number>6</number> <number>6</number>
</property> </property>
<property name="leftMargin">
<number>9</number>
</property>
<property name="topMargin">
<number>9</number>
</property>
<property name="rightMargin">
<number>9</number>
</property>
<property name="bottomMargin">
<number>9</number>
</property>
<item> <item>
<widget class="QCheckBox" name="show_shapes_cbx" > <widget class="QCheckBox" name="show_shapes_cbx">
<property name="text" > <property name="text">
<string>Show shapes when moving (max.</string> <string>Show shapes when moving (max.</string>
</property> </property>
</widget> </widget>
</item> </item>
<item> <item>
<widget class="QLineEdit" name="max_shapes_le" > <widget class="QLineEdit" name="max_shapes_le">
<property name="sizePolicy" > <property name="sizePolicy">
<sizepolicy> <sizepolicy hsizetype="Preferred" vsizetype="Fixed">
<hsizetype>5</hsizetype>
<vsizetype>0</vsizetype>
<horstretch>0</horstretch> <horstretch>0</horstretch>
<verstretch>0</verstretch> <verstretch>0</verstretch>
</sizepolicy> </sizepolicy>
@ -267,18 +355,18 @@
</widget> </widget>
</item> </item>
<item> <item>
<widget class="QLabel" name="label_13" > <widget class="QLabel" name="label_13">
<property name="text" > <property name="text">
<string>shapes)</string> <string>shapes)</string>
</property> </property>
</widget> </widget>
</item> </item>
<item> <item>
<spacer> <spacer>
<property name="orientation" > <property name="orientation">
<enum>Qt::Horizontal</enum> <enum>Qt::Horizontal</enum>
</property> </property>
<property name="sizeHint" > <property name="sizeHint" stdset="0">
<size> <size>
<width>20</width> <width>20</width>
<height>20</height> <height>20</height>
@ -291,10 +379,10 @@
</item> </item>
<item> <item>
<spacer> <spacer>
<property name="orientation" > <property name="orientation">
<enum>Qt::Vertical</enum> <enum>Qt::Vertical</enum>
</property> </property>
<property name="sizeHint" > <property name="sizeHint" stdset="0">
<size> <size>
<width>121</width> <width>121</width>
<height>51</height> <height>51</height>

View File

@ -57,6 +57,7 @@ std::string cfg_edit_inst_column_x ("edit-inst-column_x");
std::string cfg_edit_inst_column_y ("edit-inst-column_y"); std::string cfg_edit_inst_column_y ("edit-inst-column_y");
std::string cfg_edit_inst_place_origin ("edit-inst-place-origin"); std::string cfg_edit_inst_place_origin ("edit-inst-place-origin");
std::string cfg_edit_top_level_selection ("edit-top-level-selection"); std::string cfg_edit_top_level_selection ("edit-top-level-selection");
std::string cfg_edit_hier_copy_mode ("edit-hier-copy-mode");
std::string cfg_edit_show_shapes_of_instances ("edit-show-shapes-of-instances"); std::string cfg_edit_show_shapes_of_instances ("edit-show-shapes-of-instances");
std::string cfg_edit_max_shapes_of_instances ("edit-max-shapes-of-instances"); std::string cfg_edit_max_shapes_of_instances ("edit-max-shapes-of-instances");
std::string cfg_edit_global_grid ("grid-micron"); std::string cfg_edit_global_grid ("grid-micron");

View File

@ -68,6 +68,7 @@ extern EDT_PUBLIC std::string cfg_edit_inst_column_x;
extern EDT_PUBLIC std::string cfg_edit_inst_column_y; extern EDT_PUBLIC std::string cfg_edit_inst_column_y;
extern EDT_PUBLIC std::string cfg_edit_inst_place_origin; extern EDT_PUBLIC std::string cfg_edit_inst_place_origin;
extern EDT_PUBLIC std::string cfg_edit_top_level_selection; extern EDT_PUBLIC std::string cfg_edit_top_level_selection;
extern EDT_PUBLIC std::string cfg_edit_hier_copy_mode;
extern EDT_PUBLIC std::string cfg_edit_combine_mode; extern EDT_PUBLIC std::string cfg_edit_combine_mode;
// ------------------------------------------------------------ // ------------------------------------------------------------

View File

@ -196,7 +196,7 @@ CopyModeDialog::~CopyModeDialog ()
} }
bool bool
CopyModeDialog::exec_dialog (unsigned int &mode) CopyModeDialog::exec_dialog (unsigned int &mode, bool &dont_ask)
{ {
if (mode == 0) { if (mode == 0) {
shallow_rb->setChecked (true); shallow_rb->setChecked (true);
@ -207,6 +207,7 @@ CopyModeDialog::exec_dialog (unsigned int &mode)
} else { } else {
mode = 1; mode = 1;
} }
dont_ask = dont_ask_cbx->isChecked ();
return true; return true;
} else { } else {
return false; return false;

View File

@ -64,7 +64,7 @@ public:
CopyModeDialog (QWidget *parent); CopyModeDialog (QWidget *parent);
virtual ~CopyModeDialog (); virtual ~CopyModeDialog ();
bool exec_dialog (unsigned int &mode); bool exec_dialog (unsigned int &mode, bool &dont_ask);
}; };
/** /**

View File

@ -265,6 +265,8 @@ EditorOptionsGeneric::apply (lay::Plugin *root)
root->config_set (cfg_edit_connect_angle_mode, acc.to_string (lay::angle_constraint_type (mp_ui->conn_angle_cb->currentIndex ()))); root->config_set (cfg_edit_connect_angle_mode, acc.to_string (lay::angle_constraint_type (mp_ui->conn_angle_cb->currentIndex ())));
root->config_set (cfg_edit_top_level_selection, tl::to_string (mp_ui->hier_sel_cbx->isChecked ())); root->config_set (cfg_edit_top_level_selection, tl::to_string (mp_ui->hier_sel_cbx->isChecked ()));
int cpm = mp_ui->hier_copy_mode_cbx->currentIndex ();
root->config_set (cfg_edit_hier_copy_mode, tl::to_string ((cpm < 0 || cpm > 1) ? -1 : cpm));
root->config_set (cfg_edit_snap_to_objects, tl::to_string (mp_ui->snap_objects_cbx->isChecked ())); root->config_set (cfg_edit_snap_to_objects, tl::to_string (mp_ui->snap_objects_cbx->isChecked ()));
unsigned int max_shapes = 1000; unsigned int max_shapes = 1000;
@ -321,6 +323,10 @@ EditorOptionsGeneric::setup (lay::Plugin *root)
root->config_get (cfg_edit_top_level_selection, top_level_sel); root->config_get (cfg_edit_top_level_selection, top_level_sel);
mp_ui->hier_sel_cbx->setChecked (top_level_sel); mp_ui->hier_sel_cbx->setChecked (top_level_sel);
int cpm = -1;
root->config_get (cfg_edit_hier_copy_mode, cpm);
mp_ui->hier_copy_mode_cbx->setCurrentIndex ((cpm < 0 || cpm > 1) ? 2 : cpm);
bool snap_to_objects = false; bool snap_to_objects = false;
root->config_get (cfg_edit_snap_to_objects, snap_to_objects); root->config_get (cfg_edit_snap_to_objects, snap_to_objects);
mp_ui->snap_objects_cbx->setChecked (snap_to_objects); mp_ui->snap_objects_cbx->setChecked (snap_to_objects);

View File

@ -198,6 +198,7 @@ public:
virtual void get_options (std::vector < std::pair<std::string, std::string> > &options) const virtual void get_options (std::vector < std::pair<std::string, std::string> > &options) const
{ {
options.push_back (std::pair<std::string, std::string> (cfg_edit_top_level_selection, "false")); options.push_back (std::pair<std::string, std::string> (cfg_edit_top_level_selection, "false"));
options.push_back (std::pair<std::string, std::string> (cfg_edit_hier_copy_mode, "-1"));
options.push_back (std::pair<std::string, std::string> (cfg_edit_grid, "")); options.push_back (std::pair<std::string, std::string> (cfg_edit_grid, ""));
options.push_back (std::pair<std::string, std::string> (cfg_edit_snap_to_objects, "false")); options.push_back (std::pair<std::string, std::string> (cfg_edit_snap_to_objects, "false"));
options.push_back (std::pair<std::string, std::string> (cfg_edit_move_angle_mode, "any")); options.push_back (std::pair<std::string, std::string> (cfg_edit_move_angle_mode, "any"));

View File

@ -113,6 +113,7 @@ Service::Service (db::Manager *manager, lay::LayoutView *view, db::ShapeIterator
m_connect_ac (lay::AC_Any), m_move_ac (lay::AC_Any), m_alt_ac (lay::AC_Global), m_connect_ac (lay::AC_Any), m_move_ac (lay::AC_Any), m_alt_ac (lay::AC_Global),
m_snap_to_objects (false), m_snap_to_objects (false),
m_top_level_sel (false), m_show_shapes_of_instances (true), m_max_shapes_of_instances (1000), m_top_level_sel (false), m_show_shapes_of_instances (true), m_max_shapes_of_instances (1000),
m_hier_copy_mode (-1),
m_indicate_secondary_selection (false), m_indicate_secondary_selection (false),
m_seq (0), m_seq (0),
dm_selection_to_view (this, &edt::Service::do_selection_to_view) dm_selection_to_view (this, &edt::Service::do_selection_to_view)
@ -134,6 +135,7 @@ Service::Service (db::Manager *manager, lay::LayoutView *view)
m_connect_ac (lay::AC_Any), m_move_ac (lay::AC_Any), m_alt_ac (lay::AC_Global), m_connect_ac (lay::AC_Any), m_move_ac (lay::AC_Any), m_alt_ac (lay::AC_Global),
m_snap_to_objects (true), m_snap_to_objects (true),
m_top_level_sel (false), m_show_shapes_of_instances (true), m_max_shapes_of_instances (1000), m_top_level_sel (false), m_show_shapes_of_instances (true), m_max_shapes_of_instances (1000),
m_hier_copy_mode (-1),
m_indicate_secondary_selection (false), m_indicate_secondary_selection (false),
m_seq (0), m_seq (0),
dm_selection_to_view (this, &edt::Service::do_selection_to_view) dm_selection_to_view (this, &edt::Service::do_selection_to_view)
@ -255,6 +257,8 @@ Service::configure (const std::string &name, const std::string &value)
return true; // taken return true; // taken
} else if (name == cfg_edit_top_level_selection) { } else if (name == cfg_edit_top_level_selection) {
tl::from_string (value, m_top_level_sel); tl::from_string (value, m_top_level_sel);
} else if (name == cfg_edit_hier_copy_mode) {
tl::from_string (value, m_hier_copy_mode);
} }
return false; // not taken return false; // not taken
@ -309,6 +313,9 @@ Service::copy_selected ()
edt::CopyModeDialog mode_dialog (view ()); edt::CopyModeDialog mode_dialog (view ());
bool need_to_ask_for_copy_mode = false; bool need_to_ask_for_copy_mode = false;
unsigned int inst_mode = 0;
if (m_hier_copy_mode < 0) {
for (objects::const_iterator r = m_selection.begin (); r != m_selection.end () && ! need_to_ask_for_copy_mode; ++r) { for (objects::const_iterator r = m_selection.begin (); r != m_selection.end () && ! need_to_ask_for_copy_mode; ++r) {
if (r->is_cell_inst ()) { if (r->is_cell_inst ()) {
const db::Cell &cell = view ()->cellview (r->cv_index ())->layout ().cell (r->back ().inst_ptr.cell_index ()); const db::Cell &cell = view ()->cellview (r->cv_index ())->layout ().cell (r->back ().inst_ptr.cell_index ());
@ -317,10 +324,19 @@ Service::copy_selected ()
} }
} }
} }
} else {
inst_mode = (unsigned int) m_hier_copy_mode;
}
unsigned int inst_mode = 0; bool dont_ask_again = false;
if (! need_to_ask_for_copy_mode || mode_dialog.exec_dialog (inst_mode)) { if (! need_to_ask_for_copy_mode || mode_dialog.exec_dialog (inst_mode, dont_ask_again)) {
// store the given value "forever"
if (dont_ask_again) {
plugin_root ()->config_set (cfg_edit_hier_copy_mode, tl::to_string (inst_mode));
plugin_root ()->config_end ();
}
// create one ClipboardData object per cv_index because, this one assumes that there is // create one ClipboardData object per cv_index because, this one assumes that there is
// only one source layout object. // only one source layout object.
@ -357,6 +373,9 @@ Service::begin_move (lay::Editable::MoveMode mode, const db::DPoint &p, lay::ang
{ {
if (view ()->is_editable () && mode == lay::Editable::Selected) { if (view ()->is_editable () && mode == lay::Editable::Selected) {
// flush any pending updates of the markers
dm_selection_to_view.execute ();
m_move_start = p; m_move_start = p;
m_move_trans = db::DTrans (); m_move_trans = db::DTrans ();
m_move_sel = true; // TODO: there is no "false". Remove this. m_move_sel = true; // TODO: there is no "false". Remove this.
@ -1187,6 +1206,15 @@ Service::selection_applies (const lay::ObjectInstPath & /*sel*/) const
return false; return false;
} }
void
Service::transient_to_selection ()
{
if (! m_transient_selection.empty ()) {
m_selection.insert (m_transient_selection.begin (), m_transient_selection.end ());
selection_to_view ();
}
}
void void
Service::clear_previous_selection () Service::clear_previous_selection ()
{ {

View File

@ -184,11 +184,6 @@ public:
*/ */
virtual bool select (const db::DBox &box, lay::Editable::SelectionMode mode); virtual bool select (const db::DBox &box, lay::Editable::SelectionMode mode);
/**
* @brief Clears the previous selection
*/
virtual void clear_previous_selection ();
/** /**
* @brief Returns true, if the given selected object is handled by this service * @brief Returns true, if the given selected object is handled by this service
*/ */
@ -269,11 +264,21 @@ public:
*/ */
bool select (const lay::ObjectInstPath &obj, lay::Editable::SelectionMode mode); bool select (const lay::ObjectInstPath &obj, lay::Editable::SelectionMode mode);
/**
* @brief Clears the previous selection
*/
void clear_previous_selection ();
/** /**
* @brief Establish a transient selection * @brief Establish a transient selection
*/ */
bool transient_select (const db::DPoint &pos); bool transient_select (const db::DPoint &pos);
/**
* @brief Turns the transient selection to the selection
*/
virtual void transient_to_selection ();
/** /**
* @brief Clear the transient selection * @brief Clear the transient selection
*/ */
@ -574,6 +579,9 @@ private:
bool m_show_shapes_of_instances; bool m_show_shapes_of_instances;
unsigned int m_max_shapes_of_instances; unsigned int m_max_shapes_of_instances;
// Hierarchical copy mode (-1: ask, 0: shallow, 1: deep)
int m_hier_copy_mode;
// Sequence number of selection // Sequence number of selection
bool m_indicate_secondary_selection; bool m_indicate_secondary_selection;
unsigned long m_seq; unsigned long m_seq;

View File

@ -1063,6 +1063,15 @@ Service::clear_previous_selection ()
m_previous_selection.clear (); m_previous_selection.clear ();
} }
void
Service::transient_to_selection ()
{
if (mp_transient_view) {
m_selected.insert (std::make_pair (mp_transient_view->image_ref (), 0));
selection_to_view ();
}
}
bool bool
Service::select (obj_iterator obj, lay::Editable::SelectionMode mode) Service::select (obj_iterator obj, lay::Editable::SelectionMode mode)
{ {

View File

@ -304,6 +304,11 @@ public:
*/ */
virtual bool transient_select (const db::DPoint &pos); virtual bool transient_select (const db::DPoint &pos);
/**
* @brief Turns the transient selection to the selection
*/
virtual void transient_to_selection ();
/** /**
* @brief Clear the transient selection * @brief Clear the transient selection
*/ */

View File

@ -2275,7 +2275,7 @@ MainWindow::do_cm_duplicate (bool interactive)
{ {
BEGIN_PROTECTED BEGIN_PROTECTED
if (current_view () && current_view ()->has_selection ()) { if (current_view ()) {
// Do duplicate simply by concatenating copy & paste currently. // Do duplicate simply by concatenating copy & paste currently.
// Save the clipboard state before in order to preserve the current content // Save the clipboard state before in order to preserve the current content
@ -2327,7 +2327,7 @@ MainWindow::cm_copy ()
{ {
BEGIN_PROTECTED BEGIN_PROTECTED
if (current_view () && current_view ()->has_selection ()) { if (current_view ()) {
current_view ()->copy (); current_view ()->copy ();
current_view ()->clear_selection (); current_view ()->clear_selection ();
} }
@ -2370,7 +2370,7 @@ MainWindow::cm_cut ()
{ {
BEGIN_PROTECTED BEGIN_PROTECTED
if (current_view () && current_view ()->has_selection ()) { if (current_view ()) {
current_view ()->cut (); current_view ()->cut ();
current_view ()->cancel (); // see del() for reason why cancel is after cut current_view ()->cancel (); // see del() for reason why cancel is after cut
current_view ()->clear_selection (); current_view ()->clear_selection ();
@ -2766,21 +2766,6 @@ MainWindow::update_action_states ()
} }
if (mp_menu->is_valid ("edit_menu.copy")) {
Action copy_action = mp_menu->action ("edit_menu.copy");
copy_action.set_enabled (current_view () && current_view ()->has_selection () && edits_enabled ());
}
if (mp_menu->is_valid ("edit_menu.duplicate")) {
Action copy_action = mp_menu->action ("edit_menu.duplicate");
copy_action.set_enabled (current_view () && current_view ()->has_selection () && edits_enabled ());
}
if (mp_menu->is_valid ("edit_menu.cut")) {
Action cut_action = mp_menu->action ("edit_menu.cut");
cut_action.set_enabled (current_view () && current_view ()->has_selection () && edits_enabled ());
}
if (mp_menu->is_valid ("edit_menu.paste")) { if (mp_menu->is_valid ("edit_menu.paste")) {
Action paste_action = mp_menu->action ("edit_menu.paste"); Action paste_action = mp_menu->action ("edit_menu.paste");
paste_action.set_enabled (! db::Clipboard::instance ().empty () && edits_enabled ()); paste_action.set_enabled (! db::Clipboard::instance ().empty () && edits_enabled ());

View File

@ -821,6 +821,29 @@ Class<lay::LayoutView> decl_LayoutView (QT_EXTERNAL_BASE (QWidget) "lay", "Layou
"selection. Calling this method is useful to ensure there are no potential interactions with the script's " "selection. Calling this method is useful to ensure there are no potential interactions with the script's "
"functionality.\n" "functionality.\n"
) + ) +
gsi::method ("clear_selection", &lay::LayoutView::clear_selection,
"@brief Clears the selection of all objects (shapes, annotations, images ...)\n"
"\n"
"This method has been introduced in version 0.26.2\n"
) +
gsi::method ("clear_transient_selection", &lay::LayoutView::clear_transient_selection,
"@brief Clears the transient selection (mouse-over hightlights) of all objects (shapes, annotations, images ...)\n"
"\n"
"This method has been introduced in version 0.26.2\n"
) +
gsi::method ("transient_to_selection", &lay::LayoutView::transient_to_selection,
"@brief Turns the transient selection into the actual selection\n"
"\n"
"The current selection is cleared before. All highlighted objects under the mouse will become selected. "
"This applies to all types of objects (rulers, shapes, images ...).\n"
"\n"
"This method has been introduced in version 0.26.2\n"
) +
gsi::method ("selection_bbox", &lay::LayoutView::selection_bbox,
"@brief Returns the bounding box of the current selection\n"
"\n"
"This method has been introduced in version 0.26.2\n"
) +
gsi::method ("stop", &lay::LayoutView::stop, gsi::method ("stop", &lay::LayoutView::stop,
"@brief Stops redraw thread and close any browsers\n" "@brief Stops redraw thread and close any browsers\n"
"This method usually does not need to be called explicitly. The redraw thread is stopped automatically." "This method usually does not need to be called explicitly. The redraw thread is stopped automatically."
@ -1077,7 +1100,6 @@ Class<lay::LayoutView> decl_LayoutView (QT_EXTERNAL_BASE (QWidget) "lay", "Layou
) + ) +
gsi::method_ext ("delete_layers", &delete_layers1, gsi::arg ("iterators"), gsi::method_ext ("delete_layers", &delete_layers1, gsi::arg ("iterators"),
"@brief Deletes the layer properties nodes specified by the iterator\n" "@brief Deletes the layer properties nodes specified by the iterator\n"
"@args iterators\n"
"\n" "\n"
"This method deletes the nodes specifies by the iterators. This method is the most convenient way to " "This method deletes the nodes specifies by the iterators. This method is the most convenient way to "
"delete multiple entries.\n" "delete multiple entries.\n"
@ -1837,9 +1859,8 @@ static void cv_show_all_cells (lay::CellViewRef *cv)
} }
Class<lay::CellViewRef> decl_CellView ("lay", "CellView", Class<lay::CellViewRef> decl_CellView ("lay", "CellView",
method ("==", static_cast<bool (lay::CellViewRef::*) (const lay::CellViewRef &) const> (&lay::CellViewRef::operator==), method ("==", static_cast<bool (lay::CellViewRef::*) (const lay::CellViewRef &) const> (&lay::CellViewRef::operator==), gsi::arg ("other"),
"@brief Equality: indicates whether the cellviews refer to the same one\n" "@brief Equality: indicates whether the cellviews refer to the same one\n"
"@args other\n"
"In version 0.25, the definition of the equality operator has been changed to reflect identity of the " "In version 0.25, the definition of the equality operator has been changed to reflect identity of the "
"cellview. Before that version, identity of the cell shown was implied." "cellview. Before that version, identity of the cell shown was implied."
) + ) +
@ -1868,32 +1889,28 @@ Class<lay::CellViewRef> decl_CellView ("lay", "CellView",
"@brief Returns true, if the cellview is valid\n" "@brief Returns true, if the cellview is valid\n"
"A cellview may become invalid if the corresponding tab is closed for example." "A cellview may become invalid if the corresponding tab is closed for example."
) + ) +
method ("path=|set_path", &lay::CellViewRef::set_unspecific_path, method ("path=|set_path", &lay::CellViewRef::set_unspecific_path, gsi::arg ("path"),
"@brief Sets the unspecific part of the path explicitly\n" "@brief Sets the unspecific part of the path explicitly\n"
"@args path\n"
"\n" "\n"
"Setting the unspecific part of the path will clear the context path component and\n" "Setting the unspecific part of the path will clear the context path component and\n"
"update the context and target cell.\n" "update the context and target cell.\n"
) + ) +
method ("context_path=|set_context_path", &lay::CellViewRef::set_specific_path, method ("context_path=|set_context_path", &lay::CellViewRef::set_specific_path, gsi::arg ("path"),
"@brief Sets the context path explicitly\n" "@brief Sets the context path explicitly\n"
"@args path\n"
"\n" "\n"
"This method assumes that the unspecific part of the path \n" "This method assumes that the unspecific part of the path \n"
"is established already and that the context path starts\n" "is established already and that the context path starts\n"
"from the context cell.\n" "from the context cell.\n"
) + ) +
method ("cell_index=|set_cell", (void (lay::CellViewRef::*) (lay::CellViewRef::cell_index_type)) &lay::CellViewRef::set_cell, method ("cell_index=|set_cell", (void (lay::CellViewRef::*) (lay::CellViewRef::cell_index_type)) &lay::CellViewRef::set_cell, gsi::arg ("cell_index"),
"@brief Sets the path to the given cell\n" "@brief Sets the path to the given cell\n"
"@args cell_index\n"
"\n" "\n"
"This method will construct any path to this cell, not a \n" "This method will construct any path to this cell, not a \n"
"particular one. It will clear the context path\n" "particular one. It will clear the context path\n"
"and update the context and target cell. Note that the cell is specified by it's index.\n" "and update the context and target cell. Note that the cell is specified by it's index.\n"
) + ) +
method ("cell_name=|set_cell_name", (void (lay::CellViewRef::*) (const std::string &)) &lay::CellViewRef::set_cell, method ("cell_name=|set_cell_name", (void (lay::CellViewRef::*) (const std::string &)) &lay::CellViewRef::set_cell, gsi::arg ("cell_name"),
"@brief Sets the cell by name\n" "@brief Sets the cell by name\n"
"@args cell_name\n"
"\n" "\n"
"If the name is not a valid one, the cellview will become\n" "If the name is not a valid one, the cellview will become\n"
"invalid.\n" "invalid.\n"
@ -1901,9 +1918,8 @@ Class<lay::CellViewRef> decl_CellView ("lay", "CellView",
"particular one. It will clear the context path\n" "particular one. It will clear the context path\n"
"and update the context and target cell.\n" "and update the context and target cell.\n"
) + ) +
method_ext ("cell=", set_cell, method_ext ("cell=", set_cell, gsi::arg ("cell"),
"@brief Sets the cell by reference to a Cell object\n" "@brief Sets the cell by reference to a Cell object\n"
"@args cell\n"
"Setting the cell reference to nil invalidates the cellview. " "Setting the cell reference to nil invalidates the cellview. "
"This method will construct any path to this cell, not a \n" "This method will construct any path to this cell, not a \n"
"particular one. It will clear the context path\n" "particular one. It will clear the context path\n"
@ -1961,9 +1977,8 @@ Class<lay::CellViewRef> decl_CellView ("lay", "CellView",
"@brief Returns the technology name for the layout behind the given cell view\n" "@brief Returns the technology name for the layout behind the given cell view\n"
"This method has been added in version 0.23.\n" "This method has been added in version 0.23.\n"
) + ) +
method_ext ("technology=", &apply_technology, method_ext ("technology=", &apply_technology, gsi::arg ("tech_name"),
"@brief Sets the technology for the layout behind the given cell view\n" "@brief Sets the technology for the layout behind the given cell view\n"
"@args tech_name\n"
"According to the specification of the technology, new layer properties may be loaded " "According to the specification of the technology, new layer properties may be loaded "
"or the net tracer may be reconfigured. If the layout is shown in multiple views, the " "or the net tracer may be reconfigured. If the layout is shown in multiple views, the "
"technology is updated for all views.\n" "technology is updated for all views.\n"
@ -1972,9 +1987,8 @@ Class<lay::CellViewRef> decl_CellView ("lay", "CellView",
method_ext ("layout", &get_layout, method_ext ("layout", &get_layout,
"@brief Gets the reference to the layout object addressed by this view\n" "@brief Gets the reference to the layout object addressed by this view\n"
) + ) +
method_ext ("descend", &cv_descend, method_ext ("descend", &cv_descend, gsi::arg ("path"),
"@brief Descends further into the hierarchy.\n" "@brief Descends further into the hierarchy.\n"
"@args path\n"
"Adds the given path (given as an array of InstElement objects) to the specific path of the " "Adds the given path (given as an array of InstElement objects) to the specific path of the "
"cellview with the given index. In effect, the cell addressed by the terminal of the new path " "cellview with the given index. In effect, the cell addressed by the terminal of the new path "
"components can be shown in the context of the upper cells, if the minimum hierarchy level is " "components can be shown in the context of the upper cells, if the minimum hierarchy level is "

View File

@ -301,6 +301,22 @@ Editables::clear_transient_selection ()
signal_transient_selection_changed (); signal_transient_selection_changed ();
} }
void
Editables::transient_to_selection ()
{
cancel_edits ();
for (iterator e = begin (); e != end (); ++e) {
e->select (db::DBox (), lay::Editable::Reset); // clear selection
e->clear_previous_selection ();
e->transient_to_selection ();
e->clear_transient_selection ();
}
// send a signal to the observers
signal_transient_selection_changed ();
signal_selection_changed ();
}
void void
Editables::clear_selection () Editables::clear_selection ()
{ {

View File

@ -182,6 +182,14 @@ public:
return false; return false;
} }
/**
* @brief Turns the transient selection to the selection
*/
virtual void transient_to_selection ()
{
// .. nothing yet ..
}
/** /**
* @brief Clear the transient selection * @brief Clear the transient selection
* *
@ -457,6 +465,11 @@ public:
*/ */
void clear_transient_selection (); void clear_transient_selection ();
/**
* @brief Turns the transient selection to the selection
*/
void transient_to_selection ();
/** /**
* @brief Clear the previous selection * @brief Clear the previous selection
* *

View File

@ -5154,7 +5154,7 @@ LayoutView::paste_interactive ()
// operations. // operations.
trans->close (); trans->close ();
if (mp_move_service->begin_move (trans.release ())) { if (mp_move_service->begin_move (trans.release (), false)) {
switch_mode (-1); // move mode switch_mode (-1); // move mode
} }
} }
@ -5167,7 +5167,14 @@ LayoutView::copy ()
} else if (mp_control_panel && mp_control_panel->has_focus ()) { } else if (mp_control_panel && mp_control_panel->has_focus ()) {
mp_control_panel->copy (); mp_control_panel->copy ();
} else { } else {
if (lay::Editables::selection_size () == 0) {
// try to use the transient selection for the real one
lay::Editables::transient_to_selection ();
}
lay::Editables::copy (); lay::Editables::copy ();
} }
} }
@ -5182,8 +5189,15 @@ LayoutView::cut ()
db::Transaction trans (manager (), tl::to_string (QObject::tr ("Cut Layers"))); db::Transaction trans (manager (), tl::to_string (QObject::tr ("Cut Layers")));
mp_control_panel->cut (); mp_control_panel->cut ();
} else { } else {
if (lay::Editables::selection_size () == 0) {
// try to use the transient selection for the real one
lay::Editables::transient_to_selection ();
}
db::Transaction trans (manager (), tl::to_string (QObject::tr ("Cut"))); db::Transaction trans (manager (), tl::to_string (QObject::tr ("Cut")));
lay::Editables::cut (); lay::Editables::cut ();
} }
} }

View File

@ -38,6 +38,7 @@ MoveService::MoveService (lay::LayoutView *view)
: QObject (), : QObject (),
lay::ViewService (view->view_object_widget ()), lay::ViewService (view->view_object_widget ()),
m_dragging (false), m_dragging (false),
m_dragging_transient (false),
mp_editables (view), mp_editables (view),
mp_view (view), mp_view (view),
m_global_grid (0.001) m_global_grid (0.001)
@ -148,6 +149,9 @@ MoveService::mouse_move_event (const db::DPoint &p, unsigned int buttons, bool p
} }
// track mouse position for the infix move initiation
m_mouse_pos = p;
return ret; // not taken to allow the mouse tracker to receive events as well return ret; // not taken to allow the mouse tracker to receive events as well
} }
@ -163,7 +167,7 @@ MoveService::mouse_click_event (const db::DPoint &p, unsigned int buttons, bool
return true; return true;
} }
if (prio && (buttons & lay::LeftButton) != 0) { if (prio && (buttons & lay::LeftButton) != 0) {
if (handle_dragging (p, buttons, 0)) { if (handle_dragging (p, buttons, false, 0)) {
return true; return true;
} }
} }
@ -216,7 +220,7 @@ bool
MoveService::mouse_press_event (const db::DPoint &p, unsigned int buttons, bool prio) MoveService::mouse_press_event (const db::DPoint &p, unsigned int buttons, bool prio)
{ {
if (prio && (buttons & lay::LeftButton) != 0) { if (prio && (buttons & lay::LeftButton) != 0) {
if (handle_dragging (p, buttons, 0)) { if (handle_dragging (p, buttons, false, 0)) {
return true; return true;
} }
} }
@ -230,26 +234,50 @@ MoveService::mouse_press_event (const db::DPoint &p, unsigned int buttons, bool
} }
bool bool
MoveService::begin_move (db::Transaction *transaction) MoveService::begin_move (db::Transaction *transaction, bool selected_after_move)
{ {
if (m_dragging) {
return false;
}
std::auto_ptr<db::Transaction> trans_holder (transaction); std::auto_ptr<db::Transaction> trans_holder (transaction);
drag_cancel (); bool drag_transient = ! selected_after_move;
if (mp_editables->selection_size () == 0) {
// try to use the transient selection for the real one
mp_editables->transient_to_selection ();
drag_transient = true;
}
if (mp_editables->selection_size () == 0) {
// still nothing selected
return false;
}
db::DBox bbox = mp_editables->selection_bbox (); db::DBox bbox = mp_editables->selection_bbox ();
if (bbox.empty ()) { if (bbox.empty ()) {
// nothing selected // nothing (useful) selected
return false; return false;
} }
set_cursor (lay::Cursor::size_all); set_cursor (lay::Cursor::size_all);
// emulate a "begin move" at the center of the selection bbox - this will become the reference point // emulate a "begin move" at the current mouse position if inside the box or the closest point
return handle_dragging (bbox.center (), 0, trans_holder.release ()); // of the box.
db::DPoint pstart = m_mouse_pos;
if (! bbox.contains (pstart)) {
pstart.set_x (std::max (pstart.x (), bbox.p1 ().x ()));
pstart.set_x (std::min (pstart.x (), bbox.p2 ().x ()));
pstart.set_y (std::max (pstart.y (), bbox.p1 ().y ()));
pstart.set_y (std::min (pstart.y (), bbox.p2 ().y ()));
}
return handle_dragging (pstart, 0, drag_transient, trans_holder.release ());
} }
bool bool
MoveService::handle_dragging (const db::DPoint &p, unsigned int buttons, db::Transaction *transaction) MoveService::handle_dragging (const db::DPoint &p, unsigned int buttons, bool drag_transient, db::Transaction *transaction)
{ {
std::auto_ptr<db::Transaction> trans_holder (transaction); std::auto_ptr<db::Transaction> trans_holder (transaction);
@ -267,6 +295,7 @@ MoveService::handle_dragging (const db::DPoint &p, unsigned int buttons, db::Tra
mp_view->clear_transient_selection (); mp_view->clear_transient_selection ();
m_dragging = true; m_dragging = true;
m_dragging_transient = drag_transient;
widget ()->grab_mouse (this, false); widget ()->grab_mouse (this, false);
m_shift = db::DPoint (); m_shift = db::DPoint ();
@ -278,8 +307,14 @@ MoveService::handle_dragging (const db::DPoint &p, unsigned int buttons, db::Tra
} else { } else {
m_dragging = false; m_dragging = false;
widget ()->ungrab_mouse (this); widget ()->ungrab_mouse (this);
mp_editables->end_move (p, ac_from_buttons (buttons), mp_transaction.release ()); mp_editables->end_move (p, ac_from_buttons (buttons), mp_transaction.release ());
if (m_dragging_transient) {
mp_editables->clear_selection ();
}
return true; return true;
} }

View File

@ -49,7 +49,7 @@ public:
~MoveService (); ~MoveService ();
virtual bool configure (const std::string &name, const std::string &value); virtual bool configure (const std::string &name, const std::string &value);
bool begin_move (db::Transaction *transaction = 0); bool begin_move (db::Transaction *transaction = 0, bool selected_after_move = true);
private: private:
virtual bool mouse_press_event (const db::DPoint &p, unsigned int buttons, bool prio); virtual bool mouse_press_event (const db::DPoint &p, unsigned int buttons, bool prio);
@ -62,13 +62,15 @@ private:
virtual void drag_cancel (); virtual void drag_cancel ();
virtual void deactivated (); virtual void deactivated ();
bool handle_dragging (const db::DPoint &p, unsigned int buttons, db::Transaction *transaction); bool handle_dragging (const db::DPoint &p, unsigned int buttons, bool drag_transient, db::Transaction *transaction);
bool m_dragging; bool m_dragging;
bool m_dragging_transient;
lay::Editables *mp_editables; lay::Editables *mp_editables;
lay::LayoutView *mp_view; lay::LayoutView *mp_view;
double m_global_grid; double m_global_grid;
db::DPoint m_shift; db::DPoint m_shift;
db::DPoint m_mouse_pos;
std::auto_ptr<db::Transaction> mp_transaction; std::auto_ptr<db::Transaction> mp_transaction;
}; };