mirror of https://github.com/KLayout/klayout.git
commit
887914944b
|
|
@ -20,11 +20,11 @@ jobs:
|
|||
max-parallel: 12
|
||||
matrix:
|
||||
include:
|
||||
- os: "macos-13" # intel runner
|
||||
- os: "macos-15-intel" # intel runner
|
||||
cibuild: "*macosx*"
|
||||
cibw_arch: "macos_x86_64"
|
||||
macos-arch: "x86_64"
|
||||
- os: "macos-14" # M1 runner
|
||||
- os: "macos-latest" # M1 runner
|
||||
cibuild: "*macosx*"
|
||||
cibw_arch: "macos_arm64"
|
||||
macos-arch: "arm64"
|
||||
|
|
|
|||
|
|
@ -7,7 +7,7 @@
|
|||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>665</width>
|
||||
<height>103</height>
|
||||
<height>108</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="windowTitle">
|
||||
|
|
@ -56,6 +56,13 @@
|
|||
<property name="spacing">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<item row="1" column="1">
|
||||
<widget class="QRadioButton" name="ruler_diag_rb">
|
||||
<property name="text">
|
||||
<string>Diagonal</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="2">
|
||||
<widget class="QRadioButton" name="ruler_hor_rb">
|
||||
<property name="text">
|
||||
|
|
@ -77,17 +84,17 @@
|
|||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="1">
|
||||
<widget class="QRadioButton" name="ruler_diag_rb">
|
||||
<item row="0" column="3">
|
||||
<widget class="QRadioButton" name="ruler_vert_rb">
|
||||
<property name="text">
|
||||
<string>Diagonal</string>
|
||||
<string>Vertical only</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="2">
|
||||
<widget class="QRadioButton" name="ruler_vert_rb">
|
||||
<widget class="QRadioButton" name="ruler_diag_only_rb">
|
||||
<property name="text">
|
||||
<string>Vertical only</string>
|
||||
<string>Diagonal only</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
|
|
@ -102,7 +109,6 @@
|
|||
<tabstop>ruler_ortho_rb</tabstop>
|
||||
<tabstop>ruler_diag_rb</tabstop>
|
||||
<tabstop>ruler_hor_rb</tabstop>
|
||||
<tabstop>ruler_vert_rb</tabstop>
|
||||
</tabstops>
|
||||
<resources/>
|
||||
<connections/>
|
||||
|
|
|
|||
|
|
@ -644,6 +644,11 @@
|
|||
<string>Orthogonal</string>
|
||||
</property>
|
||||
</item>
|
||||
<item>
|
||||
<property name="text">
|
||||
<string>Diagonal only</string>
|
||||
</property>
|
||||
</item>
|
||||
<item>
|
||||
<property name="text">
|
||||
<string>Horizontal only</string>
|
||||
|
|
|
|||
|
|
@ -31,6 +31,7 @@ SOURCES = \
|
|||
|
||||
HEADERS += \
|
||||
antConfig.h \
|
||||
antEditorOptionsPages.h \
|
||||
antObject.h \
|
||||
antPlugin.h \
|
||||
antService.h \
|
||||
|
|
@ -40,6 +41,7 @@ HEADERS += \
|
|||
|
||||
SOURCES += \
|
||||
antConfig.cc \
|
||||
antEditorOptionsPages.cc \
|
||||
antObject.cc \
|
||||
antPlugin.cc \
|
||||
antService.cc \
|
||||
|
|
|
|||
|
|
@ -29,47 +29,6 @@ namespace ant
|
|||
// ------------------------------------------------------------
|
||||
// Helper functions to get and set the configuration
|
||||
|
||||
std::string
|
||||
ACConverter::to_string (const lay::angle_constraint_type &m)
|
||||
{
|
||||
if (m == lay::AC_Any) {
|
||||
return "any";
|
||||
} else if (m == lay::AC_Diagonal) {
|
||||
return "diagonal";
|
||||
} else if (m == lay::AC_Ortho) {
|
||||
return "ortho";
|
||||
} else if (m == lay::AC_Horizontal) {
|
||||
return "horizontal";
|
||||
} else if (m == lay::AC_Vertical) {
|
||||
return "vertical";
|
||||
} else if (m == lay::AC_Global) {
|
||||
return "global";
|
||||
} else {
|
||||
return "";
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
ACConverter::from_string (const std::string &tt, lay::angle_constraint_type &m)
|
||||
{
|
||||
std::string t (tl::trim (tt));
|
||||
if (t == "any") {
|
||||
m = lay::AC_Any;
|
||||
} else if (t == "diagonal") {
|
||||
m = lay::AC_Diagonal;
|
||||
} else if (t == "ortho") {
|
||||
m = lay::AC_Ortho;
|
||||
} else if (t == "horizontal") {
|
||||
m = lay::AC_Horizontal;
|
||||
} else if (t == "vertical") {
|
||||
m = lay::AC_Vertical;
|
||||
} else if (t == "global") {
|
||||
m = lay::AC_Global;
|
||||
} else {
|
||||
m = lay::AC_Any;
|
||||
}
|
||||
}
|
||||
|
||||
std::string
|
||||
StyleConverter::to_string (ant::Object::style_type s)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -51,12 +51,6 @@ extern ANT_PUBLIC const std::string cfg_current_ruler_template;
|
|||
// ------------------------------------------------------------
|
||||
// Helper functions to get and set the configuration
|
||||
|
||||
struct ACConverter
|
||||
{
|
||||
std::string to_string (const lay::angle_constraint_type &m);
|
||||
void from_string (const std::string &s, lay::angle_constraint_type &m);
|
||||
};
|
||||
|
||||
struct StyleConverter
|
||||
{
|
||||
std::string to_string (ant::Object::style_type s);
|
||||
|
|
|
|||
|
|
@ -159,10 +159,11 @@ ConfigPage3::setup (lay::Dispatcher *root)
|
|||
{
|
||||
// snap mode
|
||||
lay::angle_constraint_type rm = lay::AC_Any;
|
||||
root->config_get (cfg_ruler_snap_mode, rm, ACConverter ());
|
||||
root->config_get (cfg_ruler_snap_mode, rm, lay::ACConverter ());
|
||||
mp_ui->ruler_any_angle_rb->setChecked (rm == lay::AC_Any);
|
||||
mp_ui->ruler_ortho_rb->setChecked (rm == lay::AC_Ortho);
|
||||
mp_ui->ruler_diag_rb->setChecked (rm == lay::AC_Diagonal);
|
||||
mp_ui->ruler_diag_only_rb->setChecked (rm == lay::AC_DiagonalOnly);
|
||||
mp_ui->ruler_hor_rb->setChecked (rm == lay::AC_Horizontal);
|
||||
mp_ui->ruler_vert_rb->setChecked (rm == lay::AC_Vertical);
|
||||
}
|
||||
|
|
@ -180,13 +181,16 @@ ConfigPage3::commit (lay::Dispatcher *root)
|
|||
if (mp_ui->ruler_diag_rb->isChecked ()) {
|
||||
rm = lay::AC_Diagonal;
|
||||
}
|
||||
if (mp_ui->ruler_diag_only_rb->isChecked ()) {
|
||||
rm = lay::AC_DiagonalOnly;
|
||||
}
|
||||
if (mp_ui->ruler_hor_rb->isChecked ()) {
|
||||
rm = lay::AC_Horizontal;
|
||||
}
|
||||
if (mp_ui->ruler_vert_rb->isChecked ()) {
|
||||
rm = lay::AC_Vertical;
|
||||
}
|
||||
root->config_set (cfg_ruler_snap_mode, rm, ACConverter ());
|
||||
root->config_set (cfg_ruler_snap_mode, rm, lay::ACConverter ());
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------
|
||||
|
|
|
|||
|
|
@ -0,0 +1,155 @@
|
|||
|
||||
/*
|
||||
|
||||
KLayout Layout Viewer
|
||||
Copyright (C) 2006-2025 Matthias Koefferlein
|
||||
|
||||
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 2 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 for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to the Free Software
|
||||
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
|
||||
*/
|
||||
|
||||
#if defined(HAVE_QT)
|
||||
|
||||
#include "antService.h"
|
||||
#include "antEditorOptionsPages.h"
|
||||
|
||||
#include "layWidgets.h"
|
||||
#include "layDispatcher.h"
|
||||
#include "tlInternational.h"
|
||||
|
||||
#include <QHBoxLayout>
|
||||
|
||||
namespace ant
|
||||
{
|
||||
|
||||
// ------------------------------------------------------------------
|
||||
// Annotations Toolbox widget
|
||||
|
||||
ToolkitWidget::ToolkitWidget (lay::LayoutViewBase *view, lay::Dispatcher *dispatcher)
|
||||
: lay::EditorOptionsPageWidget (view, dispatcher)
|
||||
{
|
||||
mp_layout = new QHBoxLayout (this);
|
||||
|
||||
mp_x_le = new lay::DecoratedLineEdit (this);
|
||||
mp_x_le->set_label ("dx:");
|
||||
mp_layout->addWidget (mp_x_le);
|
||||
|
||||
mp_y_le = new lay::DecoratedLineEdit (this);
|
||||
mp_y_le->set_label ("dy:");
|
||||
mp_layout->addWidget (mp_y_le);
|
||||
|
||||
mp_d_le = new lay::DecoratedLineEdit (this);
|
||||
mp_d_le->set_label ("d:");
|
||||
mp_layout->addWidget (mp_d_le);
|
||||
|
||||
mp_layout->addStretch (1);
|
||||
|
||||
hide ();
|
||||
|
||||
set_toolbox_widget (true);
|
||||
set_transparent (true);
|
||||
}
|
||||
|
||||
ToolkitWidget::~ToolkitWidget ()
|
||||
{
|
||||
// .. nothing yet ..
|
||||
}
|
||||
|
||||
std::string
|
||||
ToolkitWidget::title () const
|
||||
{
|
||||
return "Box Options";
|
||||
}
|
||||
|
||||
const char *
|
||||
ToolkitWidget::name () const
|
||||
{
|
||||
return ant::Service::editor_options_name ();
|
||||
}
|
||||
|
||||
void
|
||||
ToolkitWidget::deactivated ()
|
||||
{
|
||||
hide ();
|
||||
}
|
||||
|
||||
void
|
||||
ToolkitWidget::commit (lay::Dispatcher *dispatcher)
|
||||
{
|
||||
try {
|
||||
|
||||
if (mp_d_le->hasFocus ()) {
|
||||
|
||||
double d = 0.0;
|
||||
|
||||
tl::from_string (tl::to_string (mp_d_le->text ()), d);
|
||||
|
||||
dispatcher->call_function (ant::Service::d_function_name (), tl::to_string (d));
|
||||
|
||||
} else {
|
||||
|
||||
double dx = 0.0, dy = 0.0;
|
||||
|
||||
tl::from_string (tl::to_string (mp_x_le->text ()), dx);
|
||||
tl::from_string (tl::to_string (mp_y_le->text ()), dy);
|
||||
|
||||
dispatcher->call_function (ant::Service::xy_function_name (), db::DVector (dx, dy).to_string ());
|
||||
|
||||
}
|
||||
|
||||
} catch (...) {
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
ToolkitWidget::configure (const std::string &name, const std::string &value)
|
||||
{
|
||||
if (name == ant::Service::xy_configure_name () && ! mp_x_le->hasFocus () && ! mp_y_le->hasFocus ()) {
|
||||
|
||||
try {
|
||||
|
||||
db::DVector mv;
|
||||
tl::from_string (value, mv);
|
||||
|
||||
mp_x_le->setText (tl::to_qstring (tl::micron_to_string (mv.x ())));
|
||||
mp_y_le->setText (tl::to_qstring (tl::micron_to_string (mv.y ())));
|
||||
|
||||
} catch (...) {
|
||||
}
|
||||
|
||||
} else if (name == ant::Service::d_configure_name () && ! mp_x_le->hasFocus () && ! mp_y_le->hasFocus ()) {
|
||||
|
||||
try {
|
||||
|
||||
double d;
|
||||
tl::from_string (value, d);
|
||||
|
||||
mp_d_le->setText (tl::to_qstring (tl::micron_to_string (d)));
|
||||
|
||||
} catch (...) {
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------
|
||||
// Registrations
|
||||
|
||||
// toolkit widgets
|
||||
static tl::RegisteredClass<lay::EditorOptionsPageFactoryBase> s_tookit_widget_factory (new lay::EditorOptionsPageFactory<ToolkitWidget> ("ant::Plugin"), 0);
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
|
|
@ -0,0 +1,68 @@
|
|||
|
||||
/*
|
||||
|
||||
KLayout Layout Viewer
|
||||
Copyright (C) 2006-2025 Matthias Koefferlein
|
||||
|
||||
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 2 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 for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to the Free Software
|
||||
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
|
||||
*/
|
||||
|
||||
#if defined(HAVE_QT)
|
||||
|
||||
#ifndef HDR_antEditorOptionsPages
|
||||
#define HDR_antEditorOptionsPages
|
||||
|
||||
#include "layEditorOptionsPageWidget.h"
|
||||
|
||||
class QHBoxLayout;
|
||||
|
||||
namespace lay
|
||||
{
|
||||
class DecoratedLineEdit;
|
||||
}
|
||||
|
||||
namespace ant
|
||||
{
|
||||
|
||||
/**
|
||||
* @brief The toolbox widget for annotations
|
||||
*/
|
||||
class ToolkitWidget
|
||||
: public lay::EditorOptionsPageWidget
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
ToolkitWidget (lay::LayoutViewBase *view, lay::Dispatcher *dispatcher);
|
||||
~ToolkitWidget ();
|
||||
|
||||
virtual std::string title () const;
|
||||
virtual const char *name () const;
|
||||
virtual int order () const { return 0; }
|
||||
virtual void configure (const std::string &name, const std::string &value);
|
||||
virtual void commit (lay::Dispatcher *root);
|
||||
virtual void deactivated ();
|
||||
|
||||
private:
|
||||
QHBoxLayout *mp_layout;
|
||||
lay::DecoratedLineEdit *mp_x_le, *mp_y_le, *mp_d_le;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
|
@ -24,6 +24,7 @@
|
|||
#include "antObject.h"
|
||||
#include "antTemplate.h"
|
||||
#include "antConfig.h"
|
||||
#include "layConverters.h"
|
||||
#include "tlString.h"
|
||||
#include "tlExpression.h"
|
||||
|
||||
|
|
@ -425,7 +426,24 @@ class AnnotationEvalFunction
|
|||
: public tl::EvalFunction
|
||||
{
|
||||
public:
|
||||
AnnotationEvalFunction (char function, const AnnotationEval *eval, size_t index)
|
||||
enum FunctionType {
|
||||
ManhattanLength, // L
|
||||
ManhattanLengthIncremental, // LL
|
||||
EuclidianDistance, // D
|
||||
EuclidianDistanceIncremental, // DD
|
||||
XDelta, // X
|
||||
XDeltaIncremental, // XX
|
||||
YDelta, // Y
|
||||
YDeltaIncremental, // YY
|
||||
P1X, // U
|
||||
P1Y, // V
|
||||
P2X, // P
|
||||
P2Y, // Q
|
||||
Area, // A
|
||||
Angle // G
|
||||
};
|
||||
|
||||
AnnotationEvalFunction (FunctionType function, const AnnotationEval *eval, size_t index)
|
||||
: m_function (function), mp_eval (eval), m_index (index)
|
||||
{
|
||||
// .. nothing yet ..
|
||||
|
|
@ -440,25 +458,53 @@ public:
|
|||
const Object &obj = mp_eval->obj ();
|
||||
const db::DFTrans &trans = mp_eval->trans ();
|
||||
|
||||
if (m_function == 'L') {
|
||||
out = fabs (delta_x (obj, trans)) + fabs (delta_y (obj, trans));
|
||||
} else if (m_function == 'D') {
|
||||
out = sqrt (delta_x (obj, trans) * delta_x (obj, trans) + delta_y (obj, trans) * delta_y (obj, trans));
|
||||
} else if (m_function == 'A') {
|
||||
out = delta_x (obj, trans) * delta_y (obj, trans) * 1e-6;
|
||||
} else if (m_function == 'X') {
|
||||
out = delta_x (obj, trans);
|
||||
} else if (m_function == 'Y') {
|
||||
out = delta_y (obj, trans);
|
||||
} else if (m_function == 'U') {
|
||||
out = (trans * p1 (obj)).x ();
|
||||
} else if (m_function == 'V') {
|
||||
out = (trans * p1 (obj)).y ();
|
||||
} else if (m_function == 'P') {
|
||||
out = (trans * p2 (obj)).x ();
|
||||
} else if (m_function == 'Q') {
|
||||
out = (trans * p2 (obj)).y ();
|
||||
} else if (m_function == 'G') {
|
||||
if (m_function == ManhattanLength) {
|
||||
out = fabs (delta_x (obj, trans, m_index)) + fabs (delta_y (obj, trans, m_index));
|
||||
} else if (m_function == ManhattanLengthIncremental) {
|
||||
double res = 0.0;
|
||||
for (size_t index = 0; index <= m_index; ++index) {
|
||||
res += fabs (delta_x (obj, trans, index)) + fabs (delta_y (obj, trans, index));
|
||||
}
|
||||
out = res;
|
||||
} else if (m_function == EuclidianDistance) {
|
||||
auto dx = delta_x (obj, trans, m_index);
|
||||
auto dy = delta_y (obj, trans, m_index);
|
||||
out = sqrt (dx * dx + dy * dy);
|
||||
} else if (m_function == EuclidianDistanceIncremental) {
|
||||
double res = 0.0;
|
||||
for (size_t index = 0; index <= m_index; ++index) {
|
||||
auto dx = delta_x (obj, trans, index);
|
||||
auto dy = delta_y (obj, trans, index);
|
||||
res += sqrt (dx * dx + dy * dy);
|
||||
}
|
||||
out = res;
|
||||
} else if (m_function == Area) {
|
||||
out = delta_x (obj, trans, m_index) * delta_y (obj, trans, m_index) * 1e-6;
|
||||
} else if (m_function == XDelta) {
|
||||
out = delta_x (obj, trans, m_index);
|
||||
} else if (m_function == XDeltaIncremental) {
|
||||
double res = 0.0;
|
||||
for (size_t index = 0; index <= m_index; ++index) {
|
||||
res += delta_x (obj, trans, index);
|
||||
}
|
||||
out = res;
|
||||
} else if (m_function == YDelta) {
|
||||
out = delta_y (obj, trans, m_index);
|
||||
} else if (m_function == YDeltaIncremental) {
|
||||
double res = 0.0;
|
||||
for (size_t index = 0; index <= m_index; ++index) {
|
||||
res += delta_y (obj, trans, index);
|
||||
}
|
||||
out = res;
|
||||
} else if (m_function == P1X) {
|
||||
out = (trans * p1 (obj, m_index)).x ();
|
||||
} else if (m_function == P1Y) {
|
||||
out = (trans * p1 (obj, m_index)).y ();
|
||||
} else if (m_function == P2X) {
|
||||
out = (trans * p2 (obj, m_index)).x ();
|
||||
} else if (m_function == P2Y) {
|
||||
out = (trans * p2 (obj, m_index)).y ();
|
||||
} else if (m_function == Angle) {
|
||||
double r, a1, a2;
|
||||
db::DPoint c;
|
||||
if (obj.compute_angle_parameters (r, c, a1, a2)) {
|
||||
|
|
@ -471,20 +517,20 @@ public:
|
|||
}
|
||||
}
|
||||
|
||||
db::DPoint p1 (const Object &obj) const
|
||||
db::DPoint p1 (const Object &obj, size_t index) const
|
||||
{
|
||||
return obj.seg_p1 (m_index);
|
||||
return obj.seg_p1 (index);
|
||||
}
|
||||
|
||||
db::DPoint p2 (const Object &obj) const
|
||||
db::DPoint p2 (const Object &obj, size_t index) const
|
||||
{
|
||||
return obj.seg_p2 (m_index);
|
||||
return obj.seg_p2 (index);
|
||||
}
|
||||
|
||||
double
|
||||
delta_x (const Object &obj, const db::DFTrans &t) const
|
||||
delta_x (const Object &obj, const db::DFTrans &t, size_t index) const
|
||||
{
|
||||
double dx = ((t * p2 (obj)).x () - (t * p1 (obj)).x ());
|
||||
double dx = ((t * p2 (obj, index)).x () - (t * p1 (obj, index)).x ());
|
||||
|
||||
// avoid "almost 0" outputs
|
||||
if (fabs (dx) < 1e-5 /*micron*/) {
|
||||
|
|
@ -495,9 +541,9 @@ public:
|
|||
}
|
||||
|
||||
double
|
||||
delta_y (const Object &obj, const db::DFTrans &t) const
|
||||
delta_y (const Object &obj, const db::DFTrans &t, size_t index) const
|
||||
{
|
||||
double dy = ((t * p2 (obj)).y () - (t * p1 (obj)).y ());
|
||||
double dy = ((t * p2 (obj, index)).y () - (t * p1 (obj, index)).y ());
|
||||
|
||||
// avoid "almost 0" outputs
|
||||
if (fabs (dy) < 1e-5 /*micron*/) {
|
||||
|
|
@ -508,7 +554,7 @@ public:
|
|||
}
|
||||
|
||||
private:
|
||||
char m_function;
|
||||
FunctionType m_function;
|
||||
const AnnotationEval *mp_eval;
|
||||
size_t m_index;
|
||||
};
|
||||
|
|
@ -517,16 +563,20 @@ std::string
|
|||
Object::formatted (const std::string &fmt, const db::DFTrans &t, size_t index) const
|
||||
{
|
||||
AnnotationEval eval (*this, t);
|
||||
eval.define_function ("L", new AnnotationEvalFunction('L', &eval, index)); // manhattan length
|
||||
eval.define_function ("D", new AnnotationEvalFunction('D', &eval, index)); // euclidian distance
|
||||
eval.define_function ("X", new AnnotationEvalFunction('X', &eval, index)); // x delta
|
||||
eval.define_function ("Y", new AnnotationEvalFunction('Y', &eval, index)); // y delta
|
||||
eval.define_function ("U", new AnnotationEvalFunction('U', &eval, index)); // p1.x
|
||||
eval.define_function ("V", new AnnotationEvalFunction('V', &eval, index)); // p1.y
|
||||
eval.define_function ("P", new AnnotationEvalFunction('P', &eval, index)); // p2.x
|
||||
eval.define_function ("Q", new AnnotationEvalFunction('Q', &eval, index)); // p2.y
|
||||
eval.define_function ("A", new AnnotationEvalFunction('A', &eval, index)); // area mm2
|
||||
eval.define_function ("G", new AnnotationEvalFunction('G', &eval, index)); // angle (if applicable)
|
||||
eval.define_function ("L", new AnnotationEvalFunction (AnnotationEvalFunction::ManhattanLength, &eval, index)); // manhattan length
|
||||
eval.define_function ("LL", new AnnotationEvalFunction (AnnotationEvalFunction::ManhattanLengthIncremental, &eval, index)); // manhattan length
|
||||
eval.define_function ("D", new AnnotationEvalFunction (AnnotationEvalFunction::EuclidianDistance, &eval, index)); // euclidian distance
|
||||
eval.define_function ("DD", new AnnotationEvalFunction (AnnotationEvalFunction::EuclidianDistanceIncremental, &eval, index)); // euclidian distance (incremental, for multi-rulers)
|
||||
eval.define_function ("X", new AnnotationEvalFunction (AnnotationEvalFunction::XDelta, &eval, index)); // x delta
|
||||
eval.define_function ("XX", new AnnotationEvalFunction (AnnotationEvalFunction::XDeltaIncremental, &eval, index)); // x delta (incremental, for multi-rulers)
|
||||
eval.define_function ("Y", new AnnotationEvalFunction (AnnotationEvalFunction::YDelta, &eval, index)); // y delta
|
||||
eval.define_function ("YY", new AnnotationEvalFunction (AnnotationEvalFunction::YDeltaIncremental, &eval, index)); // y delta (incremental, for multi-rulers)
|
||||
eval.define_function ("U", new AnnotationEvalFunction (AnnotationEvalFunction::P1X, &eval, index)); // p1.x
|
||||
eval.define_function ("V", new AnnotationEvalFunction (AnnotationEvalFunction::P1Y, &eval, index)); // p1.y
|
||||
eval.define_function ("P", new AnnotationEvalFunction (AnnotationEvalFunction::P2X, &eval, index)); // p2.x
|
||||
eval.define_function ("Q", new AnnotationEvalFunction (AnnotationEvalFunction::P2Y, &eval, index)); // p2.y
|
||||
eval.define_function ("A", new AnnotationEvalFunction (AnnotationEvalFunction::Area, &eval, index)); // area mm2
|
||||
eval.define_function ("G", new AnnotationEvalFunction (AnnotationEvalFunction::Angle, &eval, index)); // angle (if applicable)
|
||||
return eval.interpolate (fmt);
|
||||
}
|
||||
|
||||
|
|
@ -713,7 +763,7 @@ Object::from_string (const char *s, const char * /*base_dir*/)
|
|||
|
||||
std::string s;
|
||||
ex.read_word (s);
|
||||
ant::ACConverter sc;
|
||||
lay::ACConverter sc;
|
||||
lay::angle_constraint_type sm;
|
||||
sc.from_string (s, sm);
|
||||
angle_constraint (sm);
|
||||
|
|
@ -817,7 +867,7 @@ Object::to_string () const
|
|||
r += ",";
|
||||
|
||||
r += "angle_constraint=";
|
||||
ant::ACConverter acc;
|
||||
lay::ACConverter acc;
|
||||
r += acc.to_string (angle_constraint ());
|
||||
|
||||
return r;
|
||||
|
|
|
|||
|
|
@ -102,7 +102,7 @@ PluginDeclaration::get_options (std::vector < std::pair<std::string, std::string
|
|||
options.push_back (std::pair<std::string, std::string> (cfg_ruler_snap_range, "8"));
|
||||
options.push_back (std::pair<std::string, std::string> (cfg_ruler_color, lay::ColorConverter ().to_string (tl::Color ())));
|
||||
options.push_back (std::pair<std::string, std::string> (cfg_ruler_halo, "true"));
|
||||
options.push_back (std::pair<std::string, std::string> (cfg_ruler_snap_mode, ACConverter ().to_string (lay::AC_Any)));
|
||||
options.push_back (std::pair<std::string, std::string> (cfg_ruler_snap_mode, lay::ACConverter ().to_string (lay::AC_Any)));
|
||||
options.push_back (std::pair<std::string, std::string> (cfg_ruler_obj_snap, tl::to_string (true)));
|
||||
options.push_back (std::pair<std::string, std::string> (cfg_ruler_grid_snap, tl::to_string (false)));
|
||||
options.push_back (std::pair<std::string, std::string> (cfg_ruler_templates, std::string ()));
|
||||
|
|
@ -138,6 +138,15 @@ PluginDeclaration::create_plugin (db::Manager *manager, lay::Dispatcher *, lay::
|
|||
return new ant::Service (manager, view);
|
||||
}
|
||||
|
||||
std::vector<std::string>
|
||||
PluginDeclaration::additional_editor_options_pages () const
|
||||
{
|
||||
std::vector<std::string> names;
|
||||
// TODO: provide in a central place instead of borrowing from the edt module
|
||||
names.push_back ("GenericEditorOptions");
|
||||
return names;
|
||||
}
|
||||
|
||||
bool
|
||||
PluginDeclaration::menu_activated (const std::string &symbol) const
|
||||
{
|
||||
|
|
|
|||
|
|
@ -54,6 +54,8 @@ public:
|
|||
virtual void uninitialize (lay::Dispatcher *);
|
||||
virtual bool menu_activated (const std::string &symbol) const;
|
||||
|
||||
virtual std::vector<std::string> additional_editor_options_pages () const;
|
||||
|
||||
void register_annotation_template (const ant::Template &t, lay::Plugin *plugin = 0);
|
||||
void unregister_annotation_template (const std::string &category, lay::Plugin *plugin = 0);
|
||||
|
||||
|
|
|
|||
|
|
@ -33,6 +33,7 @@
|
|||
#include "layConverters.h"
|
||||
#include "layLayoutCanvas.h"
|
||||
#include "layFixedFont.h"
|
||||
#include "layEditorOptionsPage.h"
|
||||
#if defined(HAVE_QT)
|
||||
# include "layProperties.h"
|
||||
#endif
|
||||
|
|
@ -1041,6 +1042,12 @@ View::render (const lay::Viewport &vp, lay::ViewObjectCanvas &canvas)
|
|||
// -------------------------------------------------------------
|
||||
// ant::Service implementation
|
||||
|
||||
const char *Service::editor_options_name () { return "ant-toolkit-widget-name"; }
|
||||
const char *Service::xy_configure_name () { return "ant-toolkit-widget-xy-value"; }
|
||||
const char *Service::d_configure_name () { return "ant-toolkit-widget-d-value"; }
|
||||
const char *Service::xy_function_name () { return "ant-toolkit-widget-xy-commit"; }
|
||||
const char *Service::d_function_name () { return "ant-toolkit-widget-d-commit"; }
|
||||
|
||||
Service::Service (db::Manager *manager, lay::LayoutViewBase *view)
|
||||
: lay::EditorServiceBase (view),
|
||||
lay::Drawing (1/*number of planes*/, view->drawings ()),
|
||||
|
|
@ -1056,6 +1063,9 @@ Service::Service (db::Manager *manager, lay::LayoutViewBase *view)
|
|||
m_drawing (false), m_current (),
|
||||
m_move_mode (MoveNone),
|
||||
m_seg_index (0),
|
||||
m_length_confined (false),
|
||||
m_length (0.0),
|
||||
m_centered (false),
|
||||
m_current_template (0),
|
||||
m_hover (false),
|
||||
m_hover_wait (false),
|
||||
|
|
@ -1134,7 +1144,7 @@ Service::configure (const std::string &name, const std::string &value)
|
|||
} else if (name == cfg_ruler_snap_mode) {
|
||||
|
||||
lay::angle_constraint_type sm = lay::AC_Any;
|
||||
ACConverter ().from_string (value, sm);
|
||||
lay::ACConverter ().from_string (value, sm);
|
||||
m_snap_mode = sm;
|
||||
|
||||
} else if (name == cfg_ruler_templates) {
|
||||
|
|
@ -1169,6 +1179,21 @@ Service::config_finalize ()
|
|||
{
|
||||
}
|
||||
|
||||
void
|
||||
Service::show_toolbox (bool visible)
|
||||
{
|
||||
lay::EditorOptionsPage *tb = toolbox_widget ();
|
||||
if (tb) {
|
||||
tb->set_visible (visible);
|
||||
}
|
||||
}
|
||||
|
||||
lay::EditorOptionsPage *
|
||||
Service::toolbox_widget ()
|
||||
{
|
||||
return mp_view->editor_options_pages () ? mp_view->editor_options_pages ()->page_with_name (editor_options_name ()) : 0;
|
||||
}
|
||||
|
||||
void
|
||||
Service::annotations_changed ()
|
||||
{
|
||||
|
|
@ -1244,6 +1269,7 @@ void
|
|||
Service::drag_cancel ()
|
||||
{
|
||||
if (m_drawing) {
|
||||
show_toolbox (false);
|
||||
ui ()->ungrab_mouse (this);
|
||||
m_drawing = false;
|
||||
}
|
||||
|
|
@ -1598,72 +1624,84 @@ Service::move (const db::DPoint &p, lay::angle_constraint_type ac)
|
|||
auto ac_eff = ac == lay::AC_Global ? m_snap_mode : ac;
|
||||
clear_mouse_cursors ();
|
||||
|
||||
if (m_move_mode == MoveP1) {
|
||||
|
||||
m_current.seg_p1 (m_seg_index, snap2_visual (m_p1, p, &m_current, ac));
|
||||
m_rulers [0]->redraw ();
|
||||
|
||||
} else if (m_move_mode == MoveP2) {
|
||||
|
||||
m_current.seg_p2 (m_seg_index, snap2_visual (m_p1, p, &m_current, ac));
|
||||
m_rulers [0]->redraw ();
|
||||
|
||||
} else if (m_move_mode == MoveP12) {
|
||||
|
||||
db::DPoint p12 = snap2_visual (m_p1, p, &m_current, ac);
|
||||
m_current.seg_p1 (m_seg_index, db::DPoint (m_current.seg_p1 (m_seg_index).x(), p12.y ()));
|
||||
m_current.seg_p2 (m_seg_index, db::DPoint (p12.x (), m_current.seg_p2 (m_seg_index).y ()));
|
||||
m_rulers [0]->redraw ();
|
||||
|
||||
} else if (m_move_mode == MoveP21) {
|
||||
|
||||
db::DPoint p21 = snap2_visual (m_p1, p, &m_current, ac);
|
||||
m_current.seg_p1 (m_seg_index, db::DPoint (p21.x (), m_current.seg_p1 (m_seg_index).y ()));
|
||||
m_current.seg_p2 (m_seg_index, db::DPoint (m_current.seg_p2 (m_seg_index).x(), p21.y ()));
|
||||
m_rulers [0]->redraw ();
|
||||
|
||||
} else if (m_move_mode == MoveP1X) {
|
||||
|
||||
db::DPoint pc = snap2_visual (m_p1, p, &m_current, ac);
|
||||
m_current.seg_p1 (m_seg_index, db::DPoint (pc.x (), m_current.seg_p1 (m_seg_index).y ()));
|
||||
m_rulers [0]->redraw ();
|
||||
|
||||
} else if (m_move_mode == MoveP2X) {
|
||||
|
||||
db::DPoint pc = snap2_visual (m_p1, p, &m_current, ac);
|
||||
m_current.seg_p2 (m_seg_index, db::DPoint (pc.x (), m_current.seg_p2 (m_seg_index).y ()));
|
||||
m_rulers [0]->redraw ();
|
||||
|
||||
} else if (m_move_mode == MoveP1Y) {
|
||||
|
||||
db::DPoint pc = snap2_visual (m_p1, p, &m_current, ac);
|
||||
m_current.seg_p1 (m_seg_index, db::DPoint (m_current.seg_p1 (m_seg_index).x (), pc.y ()));
|
||||
m_rulers [0]->redraw ();
|
||||
|
||||
} else if (m_move_mode == MoveP2Y) {
|
||||
|
||||
db::DPoint pc = snap2_visual (m_p1, p, &m_current, ac);
|
||||
m_current.seg_p2 (m_seg_index, db::DPoint (m_current.seg_p2 (m_seg_index).x (), pc.y ()));
|
||||
m_rulers [0]->redraw ();
|
||||
|
||||
} else if (m_move_mode == MoveSelected) {
|
||||
if (m_move_mode == MoveSelected) {
|
||||
|
||||
db::DVector dp = p - m_p1;
|
||||
dp = lay::snap_angle (dp, ac_eff);
|
||||
|
||||
m_trans = db::DTrans (dp + (m_p1 - db::DPoint ()) - m_trans.disp ()) * m_trans * db::DTrans (db::DPoint () - m_p1);
|
||||
|
||||
propose_move_transformation (m_trans, 1);
|
||||
|
||||
snap_rulers (ac_eff);
|
||||
|
||||
for (std::vector<ant::View *>::iterator r = m_rulers.begin (); r != m_rulers.end (); ++r) {
|
||||
(*r)->transform_by (db::DCplxTrans (m_trans));
|
||||
}
|
||||
|
||||
show_message ();
|
||||
|
||||
} else if (m_move_mode != MoveNone) {
|
||||
|
||||
db::DPoint ps = snap2_visual (m_p1, p, &m_current, ac);
|
||||
m_trans = db::DTrans (ps - m_p1);
|
||||
|
||||
apply_partial_move (ps);
|
||||
|
||||
propose_move_transformation (db::DTrans (ps - m_p1), 1);
|
||||
|
||||
// display current move distance
|
||||
std::string pos = std::string ("dx: ") + tl::micron_to_string (ps.x () - m_p1.x ()) + " "
|
||||
+ "dy: " + tl::micron_to_string (ps.y () - m_p1.y ());
|
||||
view ()->message (pos);
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
Service::apply_partial_move (db::DPoint &ps)
|
||||
{
|
||||
if (m_move_mode == MoveP1) {
|
||||
|
||||
m_current.seg_p1 (m_seg_index, ps);
|
||||
|
||||
} else if (m_move_mode == MoveP2) {
|
||||
|
||||
m_current.seg_p2 (m_seg_index, ps);
|
||||
|
||||
} else if (m_move_mode == MoveP12) {
|
||||
|
||||
m_current.seg_p1 (m_seg_index, db::DPoint (m_current.seg_p1 (m_seg_index).x(), ps.y ()));
|
||||
m_current.seg_p2 (m_seg_index, db::DPoint (ps.x (), m_current.seg_p2 (m_seg_index).y ()));
|
||||
|
||||
} else if (m_move_mode == MoveP21) {
|
||||
|
||||
m_current.seg_p1 (m_seg_index, db::DPoint (ps.x (), m_current.seg_p1 (m_seg_index).y ()));
|
||||
m_current.seg_p2 (m_seg_index, db::DPoint (m_current.seg_p2 (m_seg_index).x(), ps.y ()));
|
||||
|
||||
} else if (m_move_mode == MoveP1X) {
|
||||
|
||||
ps.set_y (m_p1.y ());
|
||||
m_current.seg_p1 (m_seg_index, db::DPoint (ps.x (), m_current.seg_p1 (m_seg_index).y ()));
|
||||
|
||||
} else if (m_move_mode == MoveP2X) {
|
||||
|
||||
ps.set_y (m_p1.y ());
|
||||
m_current.seg_p2 (m_seg_index, db::DPoint (ps.x (), m_current.seg_p2 (m_seg_index).y ()));
|
||||
|
||||
} else if (m_move_mode == MoveP1Y) {
|
||||
|
||||
ps.set_x (m_p1.x ());
|
||||
m_current.seg_p1 (m_seg_index, db::DPoint (m_current.seg_p1 (m_seg_index).x (), ps.y ()));
|
||||
|
||||
} else if (m_move_mode == MoveP2Y) {
|
||||
|
||||
ps.set_x (m_p1.x ());
|
||||
m_current.seg_p2 (m_seg_index, db::DPoint (m_current.seg_p2 (m_seg_index).x (), ps.y ()));
|
||||
|
||||
}
|
||||
|
||||
if (m_move_mode != MoveSelected) {
|
||||
show_message ();
|
||||
}
|
||||
m_rulers [0]->redraw ();
|
||||
}
|
||||
|
||||
void
|
||||
|
|
@ -1676,6 +1714,13 @@ Service::show_message ()
|
|||
view ()->message (pos);
|
||||
}
|
||||
|
||||
void
|
||||
Service::end_move (const db::DVector &v)
|
||||
{
|
||||
m_trans = db::DTrans (v) * db::DTrans (m_trans.fp_trans ());
|
||||
end_move (db::DPoint (), lay::AC_Any);
|
||||
}
|
||||
|
||||
void
|
||||
Service::end_move (const db::DPoint &, lay::angle_constraint_type)
|
||||
{
|
||||
|
|
@ -1705,6 +1750,9 @@ Service::end_move (const db::DPoint &, lay::angle_constraint_type)
|
|||
|
||||
} else if (m_move_mode != MoveNone) {
|
||||
|
||||
db::DPoint ps = m_trans * m_p1;
|
||||
apply_partial_move (ps);
|
||||
|
||||
// replace the ruler that was moved
|
||||
m_current.clean_points ();
|
||||
mp_view->annotation_shapes ().replace (*m_selected.begin (), db::DUserObject (new ant::Object (m_current)));
|
||||
|
|
@ -1830,9 +1878,23 @@ Service::mouse_double_click_event (const db::DPoint & /*p*/, unsigned int button
|
|||
finish_drawing ();
|
||||
return true;
|
||||
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
bool
|
||||
Service::key_event (unsigned int key, unsigned int buttons)
|
||||
{
|
||||
if (m_drawing && buttons == 0 && (key == lay::KeyEnter || key == lay::KeyReturn)) {
|
||||
|
||||
// ends the current ruler (specifically in multi-segment mode)
|
||||
finish_drawing ();
|
||||
return true;
|
||||
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
lay::TwoPointSnapToObjectResult
|
||||
|
|
@ -1873,6 +1935,7 @@ Service::mouse_click_event (const db::DPoint &p, unsigned int buttons, bool prio
|
|||
|
||||
// cancel any edit operations so far
|
||||
m_move_mode = MoveNone;
|
||||
m_length_confined = false;
|
||||
|
||||
// reset selection
|
||||
clear_selection ();
|
||||
|
|
@ -1969,6 +2032,7 @@ Service::mouse_click_event (const db::DPoint &p, unsigned int buttons, bool prio
|
|||
mp_active_ruler->thaw ();
|
||||
m_drawing = true;
|
||||
|
||||
show_toolbox (true);
|
||||
ui ()->grab_mouse (this, false);
|
||||
|
||||
}
|
||||
|
|
@ -1989,6 +2053,7 @@ Service::mouse_click_event (const db::DPoint &p, unsigned int buttons, bool prio
|
|||
|
||||
pts.push_back (m_p1);
|
||||
m_current.set_points_exact (pts);
|
||||
m_length_confined = false;
|
||||
|
||||
}
|
||||
|
||||
|
|
@ -2021,6 +2086,116 @@ Service::create_measure_ruler (const db::DPoint &pt, lay::angle_constraint_type
|
|||
}
|
||||
}
|
||||
|
||||
void
|
||||
Service::function (const std::string &name, const std::string &value)
|
||||
{
|
||||
if (name == xy_function_name ()) {
|
||||
|
||||
try {
|
||||
|
||||
db::DVector s;
|
||||
tl::from_string (value, s);
|
||||
|
||||
if (m_drawing) {
|
||||
|
||||
ant::Object::point_list pts = m_current.points ();
|
||||
if (pts.size () >= 2) {
|
||||
|
||||
db::DVector d = pts.back () - pts [pts.size () - 2];
|
||||
|
||||
// Adjust the direction so positive coordinates are in the current drag direction
|
||||
s = db::DVector (s.x () * (d.x () < 0 ? -1.0 : 1.0), s.y () * (d.y () < 0 ? -1.0 : 1.0));
|
||||
|
||||
pts.back () = pts [pts.size () - 2] + s;
|
||||
m_current.set_points_exact (pts);
|
||||
|
||||
}
|
||||
|
||||
const ant::Template &tpl = current_template ();
|
||||
|
||||
if (tpl.mode () == ant::Template::RulerMultiSegment || tpl.mode () == ant::Template::RulerThreeClicks) {
|
||||
|
||||
if (tpl.mode () == ant::Template::RulerThreeClicks && pts.size () == 3) {
|
||||
|
||||
finish_drawing ();
|
||||
|
||||
} else {
|
||||
|
||||
// add a new point
|
||||
m_p1 = pts.back ();
|
||||
|
||||
pts.push_back (m_p1);
|
||||
m_current.set_points_exact (pts);
|
||||
|
||||
}
|
||||
|
||||
} else {
|
||||
|
||||
finish_drawing ();
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
} catch (...) {
|
||||
}
|
||||
|
||||
} else if (name == d_function_name ()) {
|
||||
|
||||
try {
|
||||
|
||||
double s = 0.0;
|
||||
tl::from_string (value, s);
|
||||
|
||||
if (m_drawing) {
|
||||
|
||||
m_length_confined = true;
|
||||
m_length = s;
|
||||
|
||||
ant::Object::point_list pts = m_current.points ();
|
||||
confine_length (pts);
|
||||
m_current.set_points_exact (pts);
|
||||
|
||||
}
|
||||
|
||||
} catch (...) {
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
Service::confine_length (ant::Object::point_list &pts)
|
||||
{
|
||||
if (m_length_confined && pts.size () >= 2) {
|
||||
|
||||
const ant::Template &tpl = current_template ();
|
||||
bool is_box_style = tpl.mode () == ant::Template::RulerNormal && (tpl.outline () == ant::Object::OL_box || tpl.outline () == ant::Object::OL_ellipse);
|
||||
|
||||
db::DPoint p1 = m_centered ? m_p1 : pts [pts.size () - 2];
|
||||
db::DVector s = pts.back () - p1;
|
||||
if (is_box_style) {
|
||||
db::DVector snew = s;
|
||||
double l = m_centered ? m_length * 0.5 : m_length;
|
||||
if (fabs (s.x ()) < fabs (s.y ()) + db::epsilon) {
|
||||
snew.set_y (l * (s.y () < 0 ? -1.0 : 1.0));
|
||||
}
|
||||
if (fabs (s.y ()) < fabs (s.x ()) + db::epsilon) {
|
||||
snew.set_x (l * (s.x () < 0 ? -1.0 : 1.0));
|
||||
}
|
||||
s = snew;
|
||||
} else {
|
||||
double l = s.double_length ();
|
||||
if (l > db::epsilon) {
|
||||
s *= m_length / l;
|
||||
}
|
||||
}
|
||||
|
||||
pts.back () = p1 + s;
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
bool
|
||||
Service::mouse_move_event (const db::DPoint &p, unsigned int buttons, bool prio)
|
||||
{
|
||||
|
|
@ -2040,11 +2215,26 @@ Service::mouse_move_event (const db::DPoint &p, unsigned int buttons, bool prio)
|
|||
|
||||
}
|
||||
|
||||
const ant::Template &tpl = current_template ();
|
||||
|
||||
// for normal rulers with box or ellipse rendering we use a different button scheme:
|
||||
// Shift will keep the center, Ctrl will confine the box to a square/ellipse to a circle
|
||||
bool is_box_style = tpl.mode () == ant::Template::RulerNormal && (tpl.outline () == ant::Object::OL_box || tpl.outline () == ant::Object::OL_ellipse);
|
||||
bool snap_square = is_box_style && (buttons & lay::ControlButton) != 0;
|
||||
m_centered = is_box_style && (buttons & lay::ShiftButton) != 0;
|
||||
|
||||
lay::PointSnapToObjectResult snap_details;
|
||||
if (m_drawing) {
|
||||
snap_details = snap2_details (m_p1, p, mp_active_ruler->ruler (), ac_from_buttons (buttons));
|
||||
lay::angle_constraint_type ac;
|
||||
if (snap_square) {
|
||||
ac = lay::AC_DiagonalOnly;
|
||||
} else if (is_box_style) {
|
||||
ac = lay::AC_Any;
|
||||
} else {
|
||||
ac = ac_from_buttons (buttons);
|
||||
}
|
||||
snap_details = snap2_details (m_p1, p, mp_active_ruler->ruler (), ac);
|
||||
} else {
|
||||
const ant::Template &tpl = current_template ();
|
||||
snap_details = snap1_details (p, m_obj_snap && tpl.snap () && (tpl.mode () != ant::Template::RulerAutoMetricEdge || ! view ()->transient_selection_mode ()));
|
||||
}
|
||||
|
||||
|
|
@ -2058,10 +2248,36 @@ Service::mouse_move_event (const db::DPoint &p, unsigned int buttons, bool prio)
|
|||
// otherwise we risk manipulating p1 too.
|
||||
ant::Object::point_list pts = m_current.points ();
|
||||
if (! pts.empty ()) {
|
||||
|
||||
pts.back () = snap_details.snapped_point;
|
||||
|
||||
confine_length (pts);
|
||||
|
||||
if (is_box_style) {
|
||||
if (m_centered) {
|
||||
pts.front () = m_p1 - (pts.back () - m_p1);
|
||||
} else {
|
||||
pts.front () = m_p1;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
m_current.set_points_exact (pts);
|
||||
|
||||
db::DVector delta;
|
||||
if (pts.size () >= 2) {
|
||||
delta = pts.back () - pts[pts.size () - 2];
|
||||
delta = db::DVector (fabs (delta.x ()), fabs (delta.y ()));
|
||||
}
|
||||
|
||||
lay::EditorOptionsPage *tb = toolbox_widget ();
|
||||
if (tb) {
|
||||
double d = is_box_style ? std::min (fabs (delta.x ()), fabs (delta.y ())) : delta.length ();
|
||||
tb->configure (xy_configure_name (), delta.to_string ());
|
||||
tb->configure (d_configure_name (), tl::to_string (d));
|
||||
}
|
||||
|
||||
mp_active_ruler->redraw ();
|
||||
show_message ();
|
||||
|
||||
|
|
|
|||
|
|
@ -197,6 +197,13 @@ Q_OBJECT
|
|||
public:
|
||||
typedef lay::AnnotationShapes::iterator obj_iterator;
|
||||
|
||||
// for communicating with the toolbox widget
|
||||
static const char *editor_options_name ();
|
||||
static const char *xy_configure_name ();
|
||||
static const char *d_configure_name ();
|
||||
static const char *xy_function_name ();
|
||||
static const char *d_function_name ();
|
||||
|
||||
/**
|
||||
* The current move mode:
|
||||
* MoveNone - not moving
|
||||
|
|
@ -347,6 +354,11 @@ public:
|
|||
*/
|
||||
virtual void end_move (const db::DPoint &p, lay::angle_constraint_type ac);
|
||||
|
||||
/**
|
||||
* @brief Terminate a "move" operation with compulsory move vector
|
||||
*/
|
||||
virtual void end_move (const db::DVector &v);
|
||||
|
||||
/**
|
||||
* @brief Return the bbox of the selection (reimplementation of lay::Editable interface)
|
||||
*/
|
||||
|
|
@ -498,10 +510,15 @@ public:
|
|||
}
|
||||
|
||||
/**
|
||||
* @brief Implement the menu response function
|
||||
* @brief Implements the menu response function
|
||||
*/
|
||||
void menu_activated (const std::string &symbol);
|
||||
|
||||
/**
|
||||
* @brief Implements the toolbox widget response function
|
||||
*/
|
||||
void function (const std::string &name, const std::string &value);
|
||||
|
||||
/**
|
||||
* @brief Return the annotation iterator that delivers the annotations (and only these)
|
||||
*/
|
||||
|
|
@ -583,6 +600,11 @@ private:
|
|||
MoveMode m_move_mode;
|
||||
// The currently moving segment
|
||||
size_t m_seg_index;
|
||||
// When set to true, the length is confined to the value given by m_length
|
||||
bool m_length_confined;
|
||||
double m_length;
|
||||
// When set to true, the last point was established in centered fashion
|
||||
bool m_centered;
|
||||
// The ruler template
|
||||
std::vector<ant::Template> m_ruler_templates;
|
||||
unsigned int m_current_template;
|
||||
|
|
@ -603,10 +625,15 @@ private:
|
|||
db::DPoint snap2_visual (const db::DPoint &p1, const db::DPoint &p2, const ant::Object *obj, lay::angle_constraint_type ac);
|
||||
lay::PointSnapToObjectResult snap2_details (const db::DPoint &p1, const db::DPoint &p2, const ant::Object *obj, lay::angle_constraint_type ac);
|
||||
lay::TwoPointSnapToObjectResult auto_measure (const db::DPoint &p, lay::angle_constraint_type ac, const ant::Template &tpl);
|
||||
void confine_length (ant::Object::point_list &pts);
|
||||
|
||||
const ant::Template ¤t_template () const;
|
||||
|
||||
void show_toolbox (bool visible);
|
||||
lay::EditorOptionsPage *toolbox_widget ();
|
||||
|
||||
void show_message ();
|
||||
void apply_partial_move (db::DPoint &ps);
|
||||
|
||||
/**
|
||||
* @brief A handler for the shape container's changed event
|
||||
|
|
@ -617,6 +644,7 @@ private:
|
|||
virtual bool mouse_press_event (const db::DPoint &p, unsigned int buttons, bool prio);
|
||||
virtual bool mouse_click_event (const db::DPoint &p, unsigned int buttons, bool prio);
|
||||
virtual bool mouse_double_click_event (const db::DPoint &p, unsigned int buttons, bool prio);
|
||||
virtual bool key_event (unsigned int key, unsigned int buttons);
|
||||
virtual void deactivated ();
|
||||
|
||||
void snap_rulers (lay::angle_constraint_type ac);
|
||||
|
|
|
|||
|
|
@ -23,6 +23,7 @@
|
|||
|
||||
#include "antTemplate.h"
|
||||
#include "antConfig.h"
|
||||
#include "layConverters.h"
|
||||
#include "tlInternational.h"
|
||||
#include "tlException.h"
|
||||
#include "tlLog.h"
|
||||
|
|
@ -263,7 +264,7 @@ Template::from_string (const std::string &s)
|
|||
|
||||
} else if (key == "angle_constraint") {
|
||||
|
||||
ant::ACConverter sc;
|
||||
lay::ACConverter sc;
|
||||
lay::angle_constraint_type sm;
|
||||
sc.from_string (s, sm);
|
||||
r.back ().angle_constraint (sm);
|
||||
|
|
@ -373,7 +374,7 @@ Template::to_string (const std::vector<Template> &v)
|
|||
r += ",";
|
||||
|
||||
r += "angle_constraint=";
|
||||
ant::ACConverter acc;
|
||||
lay::ACConverter acc;
|
||||
r += acc.to_string (t->angle_constraint ());
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -53,6 +53,7 @@ static int outline_radius () { return int (ant::Object::OL_radius); }
|
|||
|
||||
static int angle_any () { return int (lay::AC_Any); }
|
||||
static int angle_diagonal () { return int (lay::AC_Diagonal); }
|
||||
static int angle_diagonal_only () { return int (lay::AC_DiagonalOnly); }
|
||||
static int angle_ortho () { return int (lay::AC_Ortho); }
|
||||
static int angle_horizontal () { return int (lay::AC_Horizontal); }
|
||||
static int angle_vertical () { return int (lay::AC_Vertical); }
|
||||
|
|
@ -653,6 +654,11 @@ gsi::Class<AnnotationRef> decl_Annotation (decl_BasicAnnotation, "lay", "Annotat
|
|||
"@brief Gets the diagonal angle code for use with the \\angle_constraint method\n"
|
||||
"If this value is specified for the angle constraint, only multiples of 45 degree are allowed."
|
||||
) +
|
||||
gsi::method ("AngleDiagonalOnly", &gsi::angle_diagonal_only,
|
||||
"@brief Gets the diagonal angle code for use with the \\angle_constraint method\n"
|
||||
"If this value is specified for the angle constraint, only 45 degree or 135 degree are allowed.\n"
|
||||
"This constant has been introduced in version 0.30.6."
|
||||
) +
|
||||
gsi::method ("AngleOrtho", &gsi::angle_ortho,
|
||||
"@brief Gets the ortho angle code for use with the \\angle_constraint method\n"
|
||||
"If this value is specified for the angle constraint, only multiples of 90 degree are allowed."
|
||||
|
|
|
|||
|
|
@ -475,7 +475,7 @@ GenericReaderOptions::add_options (tl::CommandLineOptions &cmd)
|
|||
"For example, a datatype specification of \"6,1:61,2:62\" will use datatype 6 for via geometry without a mask assignment, "
|
||||
"datatype 61 for via geometry assigned to MASK 1 and datatype 62 for via geometry assigned to MASK 2.\n"
|
||||
"\n"
|
||||
"An alternative way to provide a layer mapping is through a map file (see '--" + m_long_prefix + "lefdef-map-file')."
|
||||
"An alternative way to provide a layer mapping is through a map file (see '--" + m_long_prefix + "lefdef-map')."
|
||||
)
|
||||
<< tl::arg (group +
|
||||
"#--" + m_long_prefix + "lefdef-via-geometry-datatype", &m_lefdef_via_geometry_datatype, "Specifies the via geometry layer datatype in pattern-based mode",
|
||||
|
|
|
|||
|
|
@ -31,6 +31,7 @@
|
|||
#include "dbEdgesUtils.h"
|
||||
#include "dbEdgePairFilters.h"
|
||||
#include "dbPropertiesFilter.h"
|
||||
#include "dbRegionProcessors.h"
|
||||
|
||||
#include "gsiDeclDbContainerHelpers.h"
|
||||
#include "gsiDeclDbMeasureHelpers.h"
|
||||
|
|
@ -531,6 +532,71 @@ static db::Region extents0 (const db::EdgePairs *r)
|
|||
return extents2 (r, 0, 0);
|
||||
}
|
||||
|
||||
namespace {
|
||||
|
||||
// a combined processor that implements db::RelativeExtents on the edge bounding boxes
|
||||
|
||||
class EdgePairsRelativeExtents
|
||||
: virtual public db::EdgePairToPolygonProcessorBase,
|
||||
virtual public db::RelativeExtents
|
||||
{
|
||||
public:
|
||||
EdgePairsRelativeExtents (double fx1, double fy1, double fx2, double fy2, db::Coord dx, db::Coord dy)
|
||||
: db::RelativeExtents (fx1, fy1, fx2, fy2, dx, dy)
|
||||
{
|
||||
// .. nothing yet ..
|
||||
}
|
||||
|
||||
// not needed, but mutes
|
||||
void process (const db::PolygonWithProperties &poly, std::vector<db::PolygonWithProperties> &result) const
|
||||
{
|
||||
db::RelativeExtents::process (poly, result);
|
||||
}
|
||||
|
||||
void process (const db::EdgePairWithProperties &ep, std::vector<db::PolygonWithProperties> &result) const
|
||||
{
|
||||
db::RelativeExtents::process (db::Polygon (ep.bbox ()), result);
|
||||
}
|
||||
};
|
||||
|
||||
class EdgePairsRelativeExtentsAsEdges
|
||||
: virtual public db::EdgePairToEdgeProcessorBase,
|
||||
virtual public db::RelativeExtentsAsEdges
|
||||
{
|
||||
public:
|
||||
EdgePairsRelativeExtentsAsEdges (double fx1, double fy1, double fx2, double fy2)
|
||||
: db::RelativeExtentsAsEdges (fx1, fy1, fx2, fy2)
|
||||
{
|
||||
// .. nothing yet ..
|
||||
}
|
||||
|
||||
void process (const db::PolygonWithProperties &poly, std::vector<db::EdgeWithProperties> &result) const
|
||||
{
|
||||
db::RelativeExtentsAsEdges::process (poly, result);
|
||||
}
|
||||
|
||||
void process (const db::EdgePairWithProperties &ep, std::vector<db::EdgeWithProperties> &result) const
|
||||
{
|
||||
db::RelativeExtentsAsEdges::process (db::Polygon (ep.bbox ()), result);
|
||||
}
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
static db::Region extent_refs (const db::EdgePairs *r, double fx1, double fy1, double fx2, double fy2, db::Coord dx, db::Coord dy)
|
||||
{
|
||||
db::Region result;
|
||||
r->processed (result, EdgePairsRelativeExtents (fx1, fy1, fx2, fy2, dx, dy));
|
||||
return result;
|
||||
}
|
||||
|
||||
static db::Edges extent_refs_edges (const db::EdgePairs *r, double fx1, double fy1, double fx2, double fy2)
|
||||
{
|
||||
db::Edges result;
|
||||
r->processed (result, EdgePairsRelativeExtentsAsEdges (fx1, fy1, fx2, fy2));
|
||||
return result;
|
||||
}
|
||||
|
||||
static db::Edges edges (const db::EdgePairs *ep)
|
||||
{
|
||||
db::Edges e;
|
||||
|
|
@ -1247,7 +1313,15 @@ Class<db::EdgePairs> decl_EdgePairs (decl_dbShapeCollection, "db", "EdgePairs",
|
|||
"The boxes will not be merged, so it is possible to determine overlaps "
|
||||
"of these boxes for example.\n"
|
||||
) +
|
||||
method_ext ("filter", &filter, gsi::arg ("filter"),
|
||||
method_ext ("extent_refs", &extent_refs,
|
||||
"@hide\n"
|
||||
"This method is provided for DRC implementation.\n"
|
||||
) +
|
||||
method_ext ("extent_refs_edges", &extent_refs_edges,
|
||||
"@hide\n"
|
||||
"This method is provided for DRC implementation.\n"
|
||||
) +
|
||||
method_ext ("filter", &filter, gsi::arg ("filter"),
|
||||
"@brief Applies a generic filter in place (replacing the edge pairs from the EdgePair collection)\n"
|
||||
"See \\EdgePairFilter for a description of this feature.\n"
|
||||
"\n"
|
||||
|
|
|
|||
|
|
@ -32,6 +32,7 @@
|
|||
#include "dbOriginalLayerRegion.h"
|
||||
#include "dbLayoutUtils.h"
|
||||
#include "dbPropertiesFilter.h"
|
||||
#include "dbRegionProcessors.h"
|
||||
|
||||
#include "gsiDeclDbContainerHelpers.h"
|
||||
#include "gsiDeclDbMeasureHelpers.h"
|
||||
|
|
@ -941,6 +942,69 @@ static std::vector<db::Edges> split_interacting_with_region (const db::Edges *r,
|
|||
return as_2edges_vector (r->selected_interacting_differential (other, min_count, max_count));
|
||||
}
|
||||
|
||||
namespace {
|
||||
|
||||
// a combined processor that implements db::RelativeExtents on the edge bounding boxes
|
||||
|
||||
class EdgesRelativeExtents
|
||||
: virtual public db::EdgeToPolygonProcessorBase,
|
||||
virtual public db::RelativeExtents
|
||||
{
|
||||
public:
|
||||
EdgesRelativeExtents (double fx1, double fy1, double fx2, double fy2, db::Coord dx, db::Coord dy)
|
||||
: db::RelativeExtents (fx1, fy1, fx2, fy2, dx, dy)
|
||||
{
|
||||
// .. nothing yet ..
|
||||
}
|
||||
|
||||
// not needed, but mutes
|
||||
void process (const db::PolygonWithProperties &poly, std::vector<db::PolygonWithProperties> &result) const
|
||||
{
|
||||
db::RelativeExtents::process (poly, result);
|
||||
}
|
||||
|
||||
void process (const db::EdgeWithProperties &edge, std::vector<db::PolygonWithProperties> &result) const
|
||||
{
|
||||
db::RelativeExtents::process (db::Polygon (edge.bbox ()), result);
|
||||
}
|
||||
};
|
||||
|
||||
class EdgesRelativeExtentsAsEdges
|
||||
: virtual public db::EdgeProcessorBase,
|
||||
virtual public db::RelativeExtentsAsEdges
|
||||
{
|
||||
public:
|
||||
EdgesRelativeExtentsAsEdges (double fx1, double fy1, double fx2, double fy2)
|
||||
: db::RelativeExtentsAsEdges (fx1, fy1, fx2, fy2)
|
||||
{
|
||||
// .. nothing yet ..
|
||||
}
|
||||
|
||||
void process (const db::PolygonWithProperties &poly, std::vector<db::EdgeWithProperties> &result) const
|
||||
{
|
||||
db::RelativeExtentsAsEdges::process (poly, result);
|
||||
}
|
||||
|
||||
void process (const db::EdgeWithProperties &edge, std::vector<db::EdgeWithProperties> &result) const
|
||||
{
|
||||
db::RelativeExtentsAsEdges::process (db::Polygon (edge.bbox ()), result);
|
||||
}
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
static db::Region extent_refs (const db::Edges *r, double fx1, double fy1, double fx2, double fy2, db::Coord dx, db::Coord dy)
|
||||
{
|
||||
db::Region result;
|
||||
r->processed (result, EdgesRelativeExtents (fx1, fy1, fx2, fy2, dx, dy));
|
||||
return result;
|
||||
}
|
||||
|
||||
static db::Edges extent_refs_edges (const db::Edges *r, double fx1, double fy1, double fx2, double fy2)
|
||||
{
|
||||
return r->processed (EdgesRelativeExtentsAsEdges (fx1, fy1, fx2, fy2));
|
||||
}
|
||||
|
||||
static tl::Variant nth (const db::Edges *edges, size_t n)
|
||||
{
|
||||
const db::Edge *e = edges->nth (n);
|
||||
|
|
@ -2372,6 +2436,14 @@ Class<db::Edges> decl_Edges (decl_dbShapeCollection, "db", "Edges",
|
|||
"The boxes will not be merged, so it is possible to determine overlaps "
|
||||
"of these boxes for example.\n"
|
||||
) +
|
||||
method_ext ("extent_refs", &extent_refs,
|
||||
"@hide\n"
|
||||
"This method is provided for DRC implementation.\n"
|
||||
) +
|
||||
method_ext ("extent_refs_edges", &extent_refs_edges,
|
||||
"@hide\n"
|
||||
"This method is provided for DRC implementation.\n"
|
||||
) +
|
||||
method_ext ("extended_in", &extended_in, gsi::arg ("e"),
|
||||
"@brief Returns a region with shapes representing the edges with the given width\n"
|
||||
"@param e The extension width\n"
|
||||
|
|
|
|||
|
|
@ -4,8 +4,8 @@
|
|||
<doc>
|
||||
|
||||
<title>About Libraries</title>
|
||||
<keyword>Library</keyword>
|
||||
<keyword>Libraries</keyword>
|
||||
<keyword name="Library"/>
|
||||
<keyword name="Libraries"/>
|
||||
|
||||
<p>
|
||||
Starting with version 0.22, KLayout offers a library concept.
|
||||
|
|
|
|||
|
|
@ -4,6 +4,7 @@
|
|||
<doc>
|
||||
|
||||
<title>About PCells</title>
|
||||
<keyword name="PCells"/>
|
||||
|
||||
<p>
|
||||
Starting with version 0.22, KLayout offers parametrized cells (PCells).
|
||||
|
|
|
|||
|
|
@ -4,6 +4,7 @@
|
|||
<doc>
|
||||
|
||||
<title>About The Basic Library</title>
|
||||
<keyword name="Basic Library"/>
|
||||
|
||||
<h2-index/>
|
||||
|
||||
|
|
|
|||
|
|
@ -4,6 +4,7 @@
|
|||
<doc>
|
||||
|
||||
<title>Connectivity</title>
|
||||
<keyword name="Connectivity"/>
|
||||
|
||||
<p>
|
||||
Use the connectivity page to specify the conductor layers and their connections.
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!DOCTYPE language SYSTEM "klayout_doc.dtd">
|
||||
|
||||
<!-- generated by /home/matthias/klayout/master/scripts/drc_lvs_doc/extract_doc.rb -->
|
||||
<!-- generated by /home/matthias/klayout/master2/scripts/drc_lvs_doc/extract_doc.rb -->
|
||||
<!-- DO NOT EDIT! -->
|
||||
|
||||
<doc>
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!DOCTYPE language SYSTEM "klayout_doc.dtd">
|
||||
|
||||
<!-- generated by /home/matthias/klayout/master/scripts/drc_lvs_doc/extract_doc.rb -->
|
||||
<!-- generated by /home/matthias/klayout/master2/scripts/drc_lvs_doc/extract_doc.rb -->
|
||||
<!-- DO NOT EDIT! -->
|
||||
|
||||
<doc>
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!DOCTYPE language SYSTEM "klayout_doc.dtd">
|
||||
|
||||
<!-- generated by /home/matthias/klayout/master/scripts/drc_lvs_doc/extract_doc.rb -->
|
||||
<!-- generated by /home/matthias/klayout/master2/scripts/drc_lvs_doc/extract_doc.rb -->
|
||||
<!-- DO NOT EDIT! -->
|
||||
|
||||
<doc>
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!DOCTYPE language SYSTEM "klayout_doc.dtd">
|
||||
|
||||
<!-- generated by /home/matthias/klayout/master/scripts/drc_lvs_doc/extract_doc.rb -->
|
||||
<!-- generated by /home/matthias/klayout/master2/scripts/drc_lvs_doc/extract_doc.rb -->
|
||||
<!-- DO NOT EDIT! -->
|
||||
|
||||
<doc>
|
||||
|
|
@ -1182,20 +1182,19 @@ The formal specifiers for lines are:
|
|||
<li><b>:right </b>or <b>:r </b>: the right line </li>
|
||||
</ul>
|
||||
</p><p>
|
||||
Dots are represented by small (2x2 DBU) boxes or point-like
|
||||
The following additional option controls the output format:
|
||||
</p><p>
|
||||
<ul>
|
||||
<li><b>as_boxes </b>: with this option, boxes (rectangular polygons) will be produced on output </li>
|
||||
<li><b>as_dots </b>or <b>as_edges </b>: with this option, edges will be produced on output </li>
|
||||
</ul>
|
||||
</p><p>
|
||||
Dots on are represented by small (2x2 DBU) boxes or point-like
|
||||
edges with edge output. Lines are represented by narrow or
|
||||
flat (2 DBU) boxes or edges for edge output. Edges will follow
|
||||
the orientation convention for the corresponding edges - i.e.
|
||||
"inside" of the bounding box is on the right side of the edge.
|
||||
</p><p>
|
||||
The following additional option controls the output format:
|
||||
</p><p>
|
||||
<ul>
|
||||
<li><b>as_boxes </b>: with this option, small boxes will be produced as markers </li>
|
||||
<li><b>as_dots </b>or <b>as_edges </b>: with this option, point-like edges will be produced for dots
|
||||
and edges will be produced for line-like selections </li>
|
||||
</ul>
|
||||
</p><p>
|
||||
The following table shows a few applications:
|
||||
</p><p>
|
||||
<table>
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!DOCTYPE language SYSTEM "klayout_doc.dtd">
|
||||
|
||||
<!-- generated by /home/matthias/klayout/master/scripts/drc_lvs_doc/extract_doc.rb -->
|
||||
<!-- generated by /home/matthias/klayout/master2/scripts/drc_lvs_doc/extract_doc.rb -->
|
||||
<!-- DO NOT EDIT! -->
|
||||
|
||||
<doc>
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!DOCTYPE language SYSTEM "klayout_doc.dtd">
|
||||
|
||||
<!-- generated by /home/matthias/klayout/master/scripts/drc_lvs_doc/extract_doc.rb -->
|
||||
<!-- generated by /home/matthias/klayout/master2/scripts/drc_lvs_doc/extract_doc.rb -->
|
||||
<!-- DO NOT EDIT! -->
|
||||
|
||||
<doc>
|
||||
|
|
|
|||
|
|
@ -4,8 +4,8 @@
|
|||
<doc>
|
||||
|
||||
<title>About Expressions</title>
|
||||
<keyword>Expressions</keyword>
|
||||
<keyword>Expression Syntax</keyword>
|
||||
<keyword name="Expressions"/>
|
||||
<keyword name="Expression Syntax"/>
|
||||
|
||||
<p>
|
||||
Beside a ruby and Python programming API, KLayout provides support for simple expressions in some places.
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!DOCTYPE language SYSTEM "klayout_doc.dtd">
|
||||
|
||||
<!-- generated by /home/matthias/klayout/master/scripts/drc_lvs_doc/extract_doc.rb -->
|
||||
<!-- generated by /home/matthias/klayout/master2/scripts/drc_lvs_doc/extract_doc.rb -->
|
||||
<!-- DO NOT EDIT! -->
|
||||
|
||||
<doc>
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!DOCTYPE language SYSTEM "klayout_doc.dtd">
|
||||
|
||||
<!-- generated by /home/matthias/klayout/master/scripts/drc_lvs_doc/extract_doc.rb -->
|
||||
<!-- generated by /home/matthias/klayout/master2/scripts/drc_lvs_doc/extract_doc.rb -->
|
||||
<!-- DO NOT EDIT! -->
|
||||
|
||||
<doc>
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!DOCTYPE language SYSTEM "klayout_doc.dtd">
|
||||
|
||||
<!-- generated by /home/matthias/klayout/master/scripts/drc_lvs_doc/extract_doc.rb -->
|
||||
<!-- generated by /home/matthias/klayout/master2/scripts/drc_lvs_doc/extract_doc.rb -->
|
||||
<!-- DO NOT EDIT! -->
|
||||
|
||||
<doc>
|
||||
|
|
|
|||
|
|
@ -14,7 +14,15 @@
|
|||
the second point. Press the ESC key to cancel the operation.
|
||||
</p>
|
||||
|
||||
<p><b>Hint:</b> A box, once created, will remain a box. For example, it is not possible to delete one vertex
|
||||
<p>
|
||||
While you drag the box, two edit boxes are shown at the top of the layout view.
|
||||
Press the Tab key to enter these edit boxes.
|
||||
Use the Tab and Shift+Tab keys to navigate between the boxes.
|
||||
You can specify numerical values for the box width and height here. Pressing the Enter key will apply these
|
||||
dimensions. Pressing the Escape key will leave the edit fields.
|
||||
</p>
|
||||
|
||||
<p><b>Note:</b> A box, once created, will remain a box. For example, it is not possible to delete one vertex
|
||||
of it, thus forming a triangle. This is only possible for polygons.
|
||||
</p>
|
||||
|
||||
|
|
|
|||
|
|
@ -18,8 +18,24 @@
|
|||
To actually draw a path,
|
||||
choose a layer from the layer panel in which to create a new path.
|
||||
Left click at the first vertex, move the mouse to the second vertex, click to place this one and continue
|
||||
to the last vertex. Double-click at the last vertex to finish the path. Press the ESC key to cancel the operation.
|
||||
Use the backspace key to remove the current segment and go back to the previous segment.
|
||||
to the last vertex. Double-click at the last vertex or press the Enter key to finish the path.
|
||||
Press the Escape key to cancel the operation.
|
||||
Use the Backspace key to remove the current segment and go back to the previous segment.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
To temporarily constrain the segment direction, press the Shift or Ctrl key or both while dragging
|
||||
the segment. Shift will apply Manhattan
|
||||
constraints (vertical and horizontal only), Ctrl will allow diagonal directions in addition and
|
||||
pressing Shift+Ctrl will allow all directions.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
While you drag a path segment, two edit boxes are shown at the top of the layout view.
|
||||
Press the Tab key to enter these edit boxes.
|
||||
Use the Tab and Shift+Tab keys to navigate between the boxes.
|
||||
You can specify a numerical values for the segment vector here. Pressing the Enter key will apply these
|
||||
relative coordinates and enter a new segment. Pressing the Escape key will leave the edit fields.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
|
|
|
|||
|
|
@ -14,11 +14,28 @@
|
|||
with a left mouse button click. Move to the next vertex. Depending on the connection mode, the edges
|
||||
created are confined to certain directions. See <link href="/manual/editor_options.xml"/>
|
||||
for a detailed description of the modes. Use the "editor options" dialog (F3 shortcut) to change the mode,
|
||||
even during editing.
|
||||
even during editing.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
Double-click at the final point to finish the polygon. Press the ESC key to cancel the operation.
|
||||
To temporarily constrain the segment direction, press the Shift or Ctrl key or both while dragging
|
||||
the segment. Shift will apply Manhattan
|
||||
constraints (vertical and horizontal only), Ctrl will allow diagonal directions in addition and
|
||||
pressing Shift+Ctrl will allow all directions.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
Double-click at the final point or press the Enter key to finish the polygon.
|
||||
Press the Escape key to cancel the operation. Use the Backspace key to delete the
|
||||
last segment.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
While you drag a polygon segment, two edit boxes are shown at the top of the layout view.
|
||||
Press the Tab key to enter these edit boxes.
|
||||
Use the Tab and Shift+Tab keys to navigate between the boxes.
|
||||
You can specify a numerical values for the segment vector here. Pressing the Enter key will apply these
|
||||
relative coordinates and enter a new segment. Pressing the Escape key will leave the edit fields.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
|
|
|
|||
|
|
@ -10,13 +10,37 @@
|
|||
<p>
|
||||
A measurement can be performed by clicking on the ruler icon in the
|
||||
toolbar and selecting "Ruler" from the drop-down options.
|
||||
Left-click on a point in the layout and then left-click again to
|
||||
specify the second point. A ruler will be shown that indicates
|
||||
the distance measured.
|
||||
Left-click on a point in the layout and then left-click again
|
||||
or press the Enter key to set the second point.
|
||||
A ruler will be shown that indicates the distance measured.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
A more convenient way is provided with the single-click measurement
|
||||
While you move the endpoint, you can hold the Shift or Ctrl key
|
||||
or both. With only the Shift key pressed, the ruler's direction
|
||||
will be limited to horizontal or vertical only. With only the Ctrl
|
||||
key pressed, the direction is limited to horizontal, vertical or
|
||||
diagonal. With Ctrl and Shift pressed together, no limitation
|
||||
of direction applies.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
While the ruler is dragged, the current drag distance is indicated
|
||||
in three edit fields at the top of the layout view. By pressing the
|
||||
Tab key, the input focus changes to these edit fields. You can
|
||||
specify a numerical value for the distances here. Use Tab and
|
||||
Shift+Tab to jump between the fields. Press the Escape key to
|
||||
leave the edit fields. Pressing the Enter key while
|
||||
the cursor is on the "dx" or "dy" field will
|
||||
accept the values and apply them to the ruler.
|
||||
If you specify a value in the last field labelled "d" and press
|
||||
Enter, the ruler will enter "fixed length" mode - in that mode you
|
||||
can still define the ruler's direction with the mouse, but the
|
||||
length is fixed to the given value.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
A convenient way to measure a distance is the single-click measurement
|
||||
ruler. Select "Measure" from the drop-down options of the ruler symbol.
|
||||
In this mode, a single click will set a ruler to the specified
|
||||
position. This feature will look for edges in the vicinity of the
|
||||
|
|
@ -24,6 +48,11 @@
|
|||
is attached perpendicular to the edge next to the initial point.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
The "Measure Edge" ruler type is also a single-click measurement
|
||||
ruler, but measures the length of an edge at the click position.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
You can mark a position with a single click by selecting the "Cross"
|
||||
ruler type. Clicking at a location will place such a ruler. The ruler
|
||||
|
|
@ -35,7 +64,12 @@
|
|||
object. Click and the first point to start such a ruler. Then click
|
||||
on more points to add new segments to the ruler. Each segment is shown
|
||||
as an individual ruler with tick marks and a length. Finish the sequence
|
||||
with a double-click.
|
||||
with a double-click or by pressing the Enter key.
|
||||
Note that the lengths indicated by the ruler labels are the lengths
|
||||
of the individual segments. To get an incremental length (the sum
|
||||
of all segment length), change the ruler's label format from "$D" to "$DD" ("DD"
|
||||
is variable giving the incremental length).
|
||||
See the description of ruler templates below, about how to make this change permanent.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
|
|
|
|||
|
|
@ -12,10 +12,16 @@
|
|||
All selected shapes are moved to the layer that is the current one (marked with a rectangle) in the layer list.
|
||||
The shapes will not be moved across the hierarchy but just inside their cell.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
All layers (source and target) must be located in the same layout. To move shapes to a
|
||||
different layout, use copy & paste.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
You can also change the layer in the shape properties. This will effectively
|
||||
move shapes to other layers too.
|
||||
</p>
|
||||
|
||||
</doc>
|
||||
|
||||
|
|
|
|||
|
|
@ -17,19 +17,27 @@
|
|||
<p>
|
||||
While moving, the whole selection can be rotated by 90 degree counterclockwise with a right mouse
|
||||
button click.
|
||||
The ESC key will cancel the operation.
|
||||
The Escape key will cancel the operation.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
For movements, the movement direction constraint apply.
|
||||
See <link href="/manual/editor_options.xml"/> for details about the modes
|
||||
available. For example, in manhattan mode, only horizontal and vertical movements are allowed.
|
||||
available. For example, in Manhattan mode, only horizontal and vertical movements are allowed.
|
||||
The global movement constraint can be overridden by pressing Shift (orthogonal), Ctrl (diagonal) or
|
||||
both Shift and Ctrl (any angle) while moving the mouse.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
If a move distance and direction is known numerically, "Move By" from the "Edit/Selection" menu can be used.
|
||||
While you move the selection, two edit boxes are shown at the top of the layout view.
|
||||
Press the Tab key to enter these edit boxes.
|
||||
Use the Tab and Shift+Tab keys to navigate between the boxes.
|
||||
You can specify a numerical shift value here. Pressing the Enter key will apply these
|
||||
shifts. Pressing the Escape key will leave the edit fields.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
To apply a specific shift, you can also use "Move By" from the "Edit/Selection" menu.
|
||||
A dialog will open that allows specification of the horizontal and vertical move distance in micrometers.
|
||||
Positive values move to the top or right and negative ones to the bottom or left.
|
||||
This dialog also applies to partial mode, so that edges or parts of a layout can be
|
||||
|
|
|
|||
|
|
@ -35,7 +35,9 @@
|
|||
Simply clicking at an item immediately enters "move" mode. In this mode, you can position the element at the desired
|
||||
target location and place it there by left-clicking at the position. Press "ESC" to cancel the operation.
|
||||
When a complex selection is made, move mode is entered by clicking at one of the selected items (the edges
|
||||
or vertices, not the shape to which they belong).
|
||||
or vertices, not the shape to which they belong). While you move, two edit boxes are shown at the top of
|
||||
the layout view. Press the Tab key to enter these edit fields. You can specify explicit move distances there.
|
||||
Press the Enter key to apply them or the Escape key to leave these edit fields.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
|
|
|
|||
|
|
@ -53,9 +53,14 @@
|
|||
|
||||
<ul>
|
||||
<li><b>$X</b>: The value of the X variable (the horizontal distance, see below for a complete list of variables).</li>
|
||||
<li><b>$(sprintf('%.2f',X))</b>: The value of the 'X' variable formatted as two digit fixed precision value.</li>
|
||||
<li><b>$(abs(X)+abs(Y))</b>: The manhattan distance of the ruler.</li>
|
||||
<li><b>$(sprintf('%.2f',X))</b>: The value of the 'X' variable formatted as two digit fixed precision value.
|
||||
The "sprintf" function follows the conventions of the same standard C function.</li>
|
||||
<li><b>$(abs(X)+abs(Y))</b>: The Manhattan distance of the ruler.</li>
|
||||
<li><b>$min(X,Y)</b>: The minimum of X and Y.</li>
|
||||
<li><b>$(X) ($Y)</b>: the value of the X variable, followed by the value of the Y variables in brackets.
|
||||
This will give a string like "2.5 (-0.5)". Note
|
||||
that you cannot simply write "$X ($Y)" because the expression evaluation reads that as an attempt to call a
|
||||
function named "X".</li>
|
||||
</ul>
|
||||
|
||||
<p>
|
||||
|
|
@ -68,7 +73,7 @@
|
|||
|
||||
<ul>
|
||||
<li><b>D:</b> The length of the ruler in micron units.</li>
|
||||
<li><b>L:</b> The manhattan length of the ruler in micron units.</li>
|
||||
<li><b>L:</b> The Manhattan length of the ruler in micron units.</li>
|
||||
<li><b>U:</b> The x-position of the ruler's first point in micron units.</li>
|
||||
<li><b>V:</b> The y-position of the ruler's first point in micron units.</li>
|
||||
<li><b>P:</b> The x-position of the ruler's second point in micron units.</li>
|
||||
|
|
@ -79,5 +84,17 @@
|
|||
<li><b>G:</b> The angle enclosed by the first and last segment of the ruler (used for angle measurement rulers).</li>
|
||||
</ul>
|
||||
|
||||
<p>
|
||||
For multi-rulers additional variables are provided for "incremental" values.
|
||||
These are the sums of the respective values up to the given part:
|
||||
</p>
|
||||
|
||||
<ul>
|
||||
<li><b>DD:</b> The sum of all lengths up to the labelled segment.</li>
|
||||
<li><b>LL:</b> The sum of all Manhattan up to the labelled segment.</li>
|
||||
<li><b>XX:</b> The horizontal distance between first and current point.</li>
|
||||
<li><b>YY:</b> The vertical distance between first and current point.</li>
|
||||
</ul>
|
||||
|
||||
</doc>
|
||||
|
||||
|
|
|
|||
|
|
@ -1463,20 +1463,19 @@ CODE
|
|||
# @li @b :right @/b or @b :r @/b: the right line @/li
|
||||
# @/ul
|
||||
#
|
||||
# Dots are represented by small (2x2 DBU) boxes or point-like
|
||||
# The following additional option controls the output format:
|
||||
#
|
||||
# @ul
|
||||
# @li @b as_boxes @/b: with this option, boxes (rectangular polygons) will be produced on output @/li
|
||||
# @li @b as_dots @/b or @b as_edges @/b: with this option, edges will be produced on output @/li
|
||||
# @/ul
|
||||
#
|
||||
# Dots on are represented by small (2x2 DBU) boxes or point-like
|
||||
# edges with edge output. Lines are represented by narrow or
|
||||
# flat (2 DBU) boxes or edges for edge output. Edges will follow
|
||||
# the orientation convention for the corresponding edges - i.e.
|
||||
# "inside" of the bounding box is on the right side of the edge.
|
||||
#
|
||||
# The following additional option controls the output format:
|
||||
#
|
||||
# @ul
|
||||
# @li @b as_boxes @/b: with this option, small boxes will be produced as markers @/li
|
||||
# @li @b as_dots @/b or @b as_edges @/b: with this option, point-like edges will be produced for dots
|
||||
# and edges will be produced for line-like selections @/li
|
||||
# @/ul
|
||||
#
|
||||
# The following table shows a few applications:
|
||||
#
|
||||
# @table
|
||||
|
|
@ -1511,7 +1510,7 @@ CODE
|
|||
|
||||
@engine._context("#{f}") do
|
||||
|
||||
requires_region
|
||||
requires_edges_edge_pairs_or_region
|
||||
|
||||
f = []
|
||||
as_edges = false
|
||||
|
|
@ -1714,7 +1713,7 @@ CODE
|
|||
dbu_trans = RBA::VCplxTrans::new(1.0 / @engine.dbu)
|
||||
|
||||
@engine.run_timed("\\"#{f}\\" in: " + @engine.src_line, self.data) do
|
||||
self.data.send(new_data.is_a?(RBA::EdgePairs) ? :each : :each_merged) do |object|
|
||||
self.data.send(self.data.is_a?(RBA::EdgePairs) ? :each : :each_merged) do |object|
|
||||
insert_object_into(new_data, block.call(object.transformed(t)), dbu_trans)
|
||||
end
|
||||
new_data
|
||||
|
|
@ -6105,6 +6104,10 @@ END
|
|||
self.data.is_a?(RBA::Edges) || self.data.is_a?(RBA::Region) || raise(name ? "#{name} requires an edge or polygon layer" : "Requires an edge or polygon layer")
|
||||
end
|
||||
|
||||
def requires_edges_edge_pairs_or_region(name = nil)
|
||||
self.data.is_a?(RBA::Edges) || self.data.is_a?(RBA::Region) || self.data.is_a?(RBA::EdgePairs) || raise(name ? "#{name} requires an edge, edge pair or polygon layer" : "Requires an edge, edge pair or polygon layer")
|
||||
end
|
||||
|
||||
def requires_edges_texts_or_region(name = nil)
|
||||
self.data.is_a?(RBA::Edges) || self.data.is_a?(RBA::Region) || self.data.is_a?(RBA::Texts) || raise(name ? "#{name} requires an edge, text or polygon layer" : "Requires an edge, text or polygon layer")
|
||||
end
|
||||
|
|
|
|||
|
|
@ -24,6 +24,7 @@
|
|||
#include "edtBoxService.h"
|
||||
|
||||
#include "layLayoutViewBase.h"
|
||||
#include "layEditorOptionsPage.h"
|
||||
|
||||
#if defined(HAVE_QT)
|
||||
# include "edtPropertiesPages.h"
|
||||
|
|
@ -35,8 +36,11 @@ namespace edt
|
|||
// -----------------------------------------------------------------------------
|
||||
// BoxService implementation
|
||||
|
||||
const char *BoxService::configure_name () { return "box-toolkit-widget-value"; }
|
||||
const char *BoxService::function_name () { return "box-toolkit-widget-commit"; }
|
||||
|
||||
BoxService::BoxService (db::Manager *manager, lay::LayoutViewBase *view)
|
||||
: ShapeEditService (manager, view, db::ShapeIterator::Boxes)
|
||||
: ShapeEditService (manager, view, db::ShapeIterator::Boxes), m_centered (false)
|
||||
{
|
||||
// .. nothing yet ..
|
||||
}
|
||||
|
|
@ -65,10 +69,42 @@ BoxService::do_begin_edit (const db::DPoint &p)
|
|||
update_marker ();
|
||||
}
|
||||
|
||||
void
|
||||
BoxService::function (const std::string &name, const std::string &value)
|
||||
{
|
||||
if (name == function_name ()) {
|
||||
|
||||
try {
|
||||
|
||||
db::DVector dim;
|
||||
tl::from_string (value, dim);
|
||||
|
||||
if (! m_centered) {
|
||||
// Adjust the direction so positive coordinates are in the current drag direction
|
||||
db::DVector d = m_p2 - m_p1;
|
||||
dim = db::DVector (dim.x () * (d.x () < 0 ? -1.0 : 1.0), dim.y () * (d.y () < 0 ? -1.0 : 1.0));
|
||||
} else {
|
||||
dim = db::DVector (fabs (dim.x ()) * 0.5, fabs (dim.y ()) * 0.5);
|
||||
}
|
||||
m_p2 = m_p1 + dim;
|
||||
|
||||
finish_editing (true);
|
||||
|
||||
} catch (...) {
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
db::Box
|
||||
BoxService::get_box () const
|
||||
{
|
||||
return db::Box (trans () * m_p1, trans () * m_p2);
|
||||
if (m_centered) {
|
||||
db::DVector d = m_p2 - m_p1;
|
||||
return db::Box (trans () * (m_p1 - d), trans () * (m_p1 + d));
|
||||
} else {
|
||||
return db::Box (trans () * m_p1, trans () * m_p2);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
|
|
@ -79,10 +115,18 @@ BoxService::update_marker ()
|
|||
|
||||
marker->set (get_box (), db::VCplxTrans (1.0 / layout ().dbu ()) * trans ().inverted ());
|
||||
|
||||
db::DVector d = m_p2 - m_p1;
|
||||
db::DVector dim = db::DVector (fabs (d.x ()), fabs (d.y ())) * (m_centered ? 2.0 : 1.0);
|
||||
|
||||
view ()->message (std::string ("lx: ") +
|
||||
tl::micron_to_string (m_p2.x () - m_p1.x ()) +
|
||||
tl::micron_to_string (dim.x ()) +
|
||||
std::string (" ly: ") +
|
||||
tl::micron_to_string (m_p2.y () - m_p1.y ()));
|
||||
tl::micron_to_string (dim.y ()));
|
||||
|
||||
auto p = toolbox_widget ();
|
||||
if (p) {
|
||||
p->configure (configure_name (), dim.to_string ());
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
|
@ -108,10 +152,14 @@ BoxService::do_mouse_move_inactive (const db::DPoint &p)
|
|||
void
|
||||
BoxService::do_mouse_move (const db::DPoint &p)
|
||||
{
|
||||
lay::PointSnapToObjectResult snap_details = snap2_details (p);
|
||||
// snap to square if Ctrl button is pressed
|
||||
bool snap_square = (mouse_buttons () & lay::ControlButton) != 0;
|
||||
bool centered = (mouse_buttons () & lay::ShiftButton) != 0;
|
||||
|
||||
lay::PointSnapToObjectResult snap_details = snap2_details (p, m_p1, snap_square ? lay::AC_DiagonalOnly : lay::AC_Any);
|
||||
db::DPoint ps = snap_details.snapped_point;
|
||||
|
||||
if (snap_details.object_snap == lay::PointSnapToObjectResult::NoObject) {
|
||||
if (snap_details.object_snap == lay::PointSnapToObjectResult::NoObject && ! m_centered) {
|
||||
|
||||
clear_mouse_cursors ();
|
||||
|
||||
|
|
@ -122,12 +170,22 @@ BoxService::do_mouse_move (const db::DPoint &p)
|
|||
lay::PointSnapToObjectResult snap_details_y = snap2_details (py);
|
||||
|
||||
if (snap_details_x.object_snap != lay::PointSnapToObjectResult::NoObject) {
|
||||
ps = db::DPoint (snap_details_x.snapped_point.x (), ps.y ());
|
||||
if (snap_square) {
|
||||
double dx = fabs (snap_details_x.snapped_point.x () - m_p1.x ());
|
||||
ps = db::DPoint (snap_details_x.snapped_point.x (), m_p1.y () + (ps.y () < m_p1.y () ? -dx : dx));
|
||||
} else {
|
||||
ps = db::DPoint (snap_details_x.snapped_point.x (), ps.y ());
|
||||
}
|
||||
mouse_cursor_from_snap_details (snap_details_x, true /*add*/);
|
||||
}
|
||||
|
||||
if (snap_details_y.object_snap != lay::PointSnapToObjectResult::NoObject) {
|
||||
ps = db::DPoint (ps.x (), snap_details_y.snapped_point.y ());
|
||||
if (snap_square) {
|
||||
double dy = fabs (snap_details_y.snapped_point.x () - m_p1.y ());
|
||||
ps = db::DPoint (m_p1.x () + (ps.x () < m_p1.x () ? -dy : dy), snap_details_y.snapped_point.y ());
|
||||
} else {
|
||||
ps = db::DPoint (ps.x (), snap_details_y.snapped_point.y ());
|
||||
}
|
||||
mouse_cursor_from_snap_details (snap_details_y, true /*add*/);
|
||||
}
|
||||
|
||||
|
|
@ -139,6 +197,7 @@ BoxService::do_mouse_move (const db::DPoint &p)
|
|||
|
||||
set_cursor (lay::Cursor::cross);
|
||||
m_p2 = ps;
|
||||
m_centered = centered;
|
||||
update_marker ();
|
||||
}
|
||||
|
||||
|
|
@ -150,7 +209,7 @@ BoxService::do_mouse_click (const db::DPoint &p)
|
|||
}
|
||||
|
||||
void
|
||||
BoxService::do_finish_edit ()
|
||||
BoxService::do_finish_edit (bool /*accept*/)
|
||||
{
|
||||
deliver_shape (get_box ());
|
||||
commit_recent ();
|
||||
|
|
|
|||
|
|
@ -36,6 +36,9 @@ class BoxService
|
|||
: public ShapeEditService
|
||||
{
|
||||
public:
|
||||
static const char *configure_name ();
|
||||
static const char *function_name ();
|
||||
|
||||
BoxService (db::Manager *manager, lay::LayoutViewBase *view);
|
||||
|
||||
#if defined(HAVE_QT)
|
||||
|
|
@ -45,12 +48,14 @@ public:
|
|||
virtual void do_mouse_move (const db::DPoint &p);
|
||||
virtual void do_mouse_move_inactive (const db::DPoint &p);
|
||||
virtual bool do_mouse_click (const db::DPoint &p);
|
||||
virtual void do_finish_edit ();
|
||||
virtual void do_finish_edit (bool accept);
|
||||
virtual void do_cancel_edit ();
|
||||
virtual bool selection_applies (const lay::ObjectInstPath &sel) const;
|
||||
virtual void function (const std::string &name, const std::string &value);
|
||||
|
||||
private:
|
||||
db::DPoint m_p1, m_p2;
|
||||
bool m_centered;
|
||||
|
||||
void update_marker ();
|
||||
db::Box get_box () const;
|
||||
|
|
|
|||
|
|
@ -29,6 +29,7 @@
|
|||
#include "edtPCellParametersPage.h"
|
||||
#include "edtConfig.h"
|
||||
#include "edtService.h"
|
||||
#include "edtBoxService.h"
|
||||
#include "edtEditorOptionsPages.h"
|
||||
#include "edtPropertiesPageUtils.h"
|
||||
#include "tlExceptions.h"
|
||||
|
|
@ -72,7 +73,7 @@ static void configure_from_line_edit (lay::Dispatcher *dispatcher, QLineEdit *le
|
|||
// EditorOptionsGeneric implementation
|
||||
|
||||
EditorOptionsGeneric::EditorOptionsGeneric (lay::LayoutViewBase *view, lay::Dispatcher *dispatcher)
|
||||
: EditorOptionsPage (view, dispatcher)
|
||||
: lay::EditorOptionsPageWidget (view, dispatcher)
|
||||
{
|
||||
mp_ui = new Ui::EditorOptionsGeneric ();
|
||||
mp_ui->setupUi (this);
|
||||
|
|
@ -215,7 +216,7 @@ EditorOptionsGeneric::setup (lay::Dispatcher *root)
|
|||
// EditorOptionsText implementation
|
||||
|
||||
EditorOptionsText::EditorOptionsText (lay::LayoutViewBase *view, lay::Dispatcher *dispatcher)
|
||||
: lay::EditorOptionsPage (view, dispatcher)
|
||||
: lay::EditorOptionsPageWidget (view, dispatcher)
|
||||
{
|
||||
mp_ui = new Ui::EditorOptionsText ();
|
||||
mp_ui->setupUi (this);
|
||||
|
|
@ -293,7 +294,7 @@ EditorOptionsText::setup (lay::Dispatcher *root)
|
|||
// EditorOptionsPath implementation
|
||||
|
||||
EditorOptionsPath::EditorOptionsPath (lay::LayoutViewBase *view, lay::Dispatcher *dispatcher)
|
||||
: lay::EditorOptionsPage (view, dispatcher)
|
||||
: lay::EditorOptionsPageWidget (view, dispatcher)
|
||||
{
|
||||
mp_ui = new Ui::EditorOptionsPath ();
|
||||
mp_ui->setupUi (this);
|
||||
|
|
@ -394,7 +395,7 @@ EditorOptionsPath::setup (lay::Dispatcher *root)
|
|||
// EditorOptionsInst implementation
|
||||
|
||||
EditorOptionsInst::EditorOptionsInst (lay::LayoutViewBase *view, lay::Dispatcher *dispatcher)
|
||||
: lay::EditorOptionsPage (view, dispatcher)
|
||||
: lay::EditorOptionsPageWidget (view, dispatcher)
|
||||
{
|
||||
mp_ui = new Ui::EditorOptionsInst ();
|
||||
mp_ui->setupUi (this);
|
||||
|
|
@ -687,7 +688,7 @@ EditorOptionsInst::setup (lay::Dispatcher *root)
|
|||
// EditorOptionsInstPCellParam implementation
|
||||
|
||||
EditorOptionsInstPCellParam::EditorOptionsInstPCellParam (lay::LayoutViewBase *view, lay::Dispatcher *dispatcher)
|
||||
: lay::EditorOptionsPage (view, dispatcher), mp_pcell_parameters (0), mp_placeholder_label (0)
|
||||
: lay::EditorOptionsPageWidget (view, dispatcher), mp_pcell_parameters (0), mp_placeholder_label (0)
|
||||
{
|
||||
mp_ui = new Ui::EditorOptionsInstPCellParam ();
|
||||
mp_ui->setupUi (this);
|
||||
|
|
@ -898,6 +899,348 @@ EditorOptionsInstPCellParam::update_pcell_parameters (const std::vector <tl::Var
|
|||
}
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------
|
||||
// Box toolbox widget
|
||||
|
||||
BoxToolboxWidget::BoxToolboxWidget (lay::LayoutViewBase *view, lay::Dispatcher *dispatcher)
|
||||
: lay::EditorOptionsPageWidget (view, dispatcher)
|
||||
{
|
||||
mp_layout = new QHBoxLayout (this);
|
||||
|
||||
mp_x_le = new lay::DecoratedLineEdit (this);
|
||||
mp_x_le->set_label ("w:");
|
||||
mp_layout->addWidget (mp_x_le);
|
||||
|
||||
mp_y_le = new lay::DecoratedLineEdit (this);
|
||||
mp_y_le->set_label ("h:");
|
||||
mp_layout->addWidget (mp_y_le);
|
||||
|
||||
mp_layout->addStretch (1);
|
||||
|
||||
hide ();
|
||||
|
||||
set_toolbox_widget (true);
|
||||
set_transparent (true);
|
||||
}
|
||||
|
||||
BoxToolboxWidget::~BoxToolboxWidget ()
|
||||
{
|
||||
// .. nothing yet ..
|
||||
}
|
||||
|
||||
std::string
|
||||
BoxToolboxWidget::title () const
|
||||
{
|
||||
return "Box Options";
|
||||
}
|
||||
|
||||
void
|
||||
BoxToolboxWidget::deactivated ()
|
||||
{
|
||||
hide ();
|
||||
}
|
||||
|
||||
void
|
||||
BoxToolboxWidget::commit (lay::Dispatcher *dispatcher)
|
||||
{
|
||||
try {
|
||||
|
||||
double dx = 0.0, dy = 0.0;
|
||||
|
||||
tl::from_string (tl::to_string (mp_x_le->text ()), dx);
|
||||
tl::from_string (tl::to_string (mp_y_le->text ()), dy);
|
||||
|
||||
dispatcher->call_function (BoxService::function_name (), db::DVector (dx, dy).to_string ());
|
||||
|
||||
} catch (...) {
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
BoxToolboxWidget::configure (const std::string &name, const std::string &value)
|
||||
{
|
||||
if (name == BoxService::configure_name () && ! mp_x_le->hasFocus () && ! mp_y_le->hasFocus ()) {
|
||||
|
||||
try {
|
||||
|
||||
db::DVector mv;
|
||||
tl::from_string (value, mv);
|
||||
|
||||
mp_x_le->setText (tl::to_qstring (tl::micron_to_string (mv.x ())));
|
||||
mp_y_le->setText (tl::to_qstring (tl::micron_to_string (mv.y ())));
|
||||
|
||||
} catch (...) {
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------
|
||||
// Connections toolbox widget (for polygons)
|
||||
|
||||
ConnectionToolboxWidget::ConnectionToolboxWidget (lay::LayoutViewBase *view, lay::Dispatcher *dispatcher)
|
||||
: lay::EditorOptionsPageWidget (view, dispatcher), m_in_commit (false)
|
||||
{
|
||||
mp_layout = new QHBoxLayout (this);
|
||||
|
||||
mp_x_le = new lay::DecoratedLineEdit (this);
|
||||
mp_x_le->set_label ("dx:");
|
||||
mp_layout->addWidget (mp_x_le);
|
||||
|
||||
mp_y_le = new lay::DecoratedLineEdit (this);
|
||||
mp_y_le->set_label ("dy:");
|
||||
mp_layout->addWidget (mp_y_le);
|
||||
|
||||
mp_layout->addStretch (1);
|
||||
|
||||
hide ();
|
||||
|
||||
set_toolbox_widget (true);
|
||||
set_transparent (true);
|
||||
}
|
||||
|
||||
ConnectionToolboxWidget::~ConnectionToolboxWidget ()
|
||||
{
|
||||
// .. nothing yet ..
|
||||
}
|
||||
|
||||
std::string
|
||||
ConnectionToolboxWidget::title () const
|
||||
{
|
||||
return "Connection Options";
|
||||
}
|
||||
|
||||
void
|
||||
ConnectionToolboxWidget::deactivated ()
|
||||
{
|
||||
hide ();
|
||||
}
|
||||
|
||||
void
|
||||
ConnectionToolboxWidget::commit (lay::Dispatcher *dispatcher)
|
||||
{
|
||||
m_in_commit = true;
|
||||
|
||||
try {
|
||||
|
||||
double dx = 0.0, dy = 0.0;
|
||||
|
||||
tl::from_string (tl::to_string (mp_x_le->text ()), dx);
|
||||
tl::from_string (tl::to_string (mp_y_le->text ()), dy);
|
||||
|
||||
dispatcher->call_function (ShapeEditService::connection_function_name (), db::DVector (dx, dy).to_string ());
|
||||
|
||||
} catch (...) {
|
||||
}
|
||||
|
||||
m_in_commit = false;
|
||||
}
|
||||
|
||||
void
|
||||
ConnectionToolboxWidget::configure (const std::string &name, const std::string &value)
|
||||
{
|
||||
if (name == ShapeEditService::connection_configure_name () &&
|
||||
((! mp_x_le->hasFocus () && ! mp_y_le->hasFocus ()) || m_in_commit)) {
|
||||
|
||||
try {
|
||||
|
||||
db::DVector mv;
|
||||
tl::from_string (value, mv);
|
||||
|
||||
mp_x_le->setText (tl::to_qstring (tl::micron_to_string (mv.x ())));
|
||||
mp_y_le->setText (tl::to_qstring (tl::micron_to_string (mv.y ())));
|
||||
|
||||
} catch (...) {
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------
|
||||
// Connections toolbox widget (for paths)
|
||||
|
||||
PathConnectionToolboxWidget::PathConnectionToolboxWidget (lay::LayoutViewBase *view, lay::Dispatcher *dispatcher)
|
||||
: lay::EditorOptionsPageWidget (view, dispatcher), m_in_commit (false)
|
||||
{
|
||||
mp_layout = new QHBoxLayout (this);
|
||||
|
||||
mp_x_le = new lay::DecoratedLineEdit (this);
|
||||
mp_x_le->set_label ("dx:");
|
||||
mp_layout->addWidget (mp_x_le);
|
||||
|
||||
mp_y_le = new lay::DecoratedLineEdit (this);
|
||||
mp_y_le->set_label ("dy:");
|
||||
mp_layout->addWidget (mp_y_le);
|
||||
|
||||
mp_width = new lay::DecoratedLineEdit (this);
|
||||
mp_width->set_label ("w:");
|
||||
mp_layout->addWidget (mp_width);
|
||||
|
||||
mp_layout->addStretch (1);
|
||||
|
||||
hide ();
|
||||
|
||||
set_toolbox_widget (true);
|
||||
set_transparent (true);
|
||||
}
|
||||
|
||||
PathConnectionToolboxWidget::~PathConnectionToolboxWidget ()
|
||||
{
|
||||
// .. nothing yet ..
|
||||
}
|
||||
|
||||
std::string
|
||||
PathConnectionToolboxWidget::title () const
|
||||
{
|
||||
return "Path Connection Options";
|
||||
}
|
||||
|
||||
void
|
||||
PathConnectionToolboxWidget::deactivated ()
|
||||
{
|
||||
hide ();
|
||||
}
|
||||
|
||||
void
|
||||
PathConnectionToolboxWidget::commit (lay::Dispatcher *dispatcher)
|
||||
{
|
||||
m_in_commit = true;
|
||||
|
||||
try {
|
||||
|
||||
if (mp_x_le->hasFocus () || mp_y_le->hasFocus ()) {
|
||||
|
||||
double dx = 0.0, dy = 0.0;
|
||||
|
||||
tl::from_string (tl::to_string (mp_x_le->text ()), dx);
|
||||
tl::from_string (tl::to_string (mp_y_le->text ()), dy);
|
||||
|
||||
dispatcher->call_function (ShapeEditService::connection_function_name (), db::DVector (dx, dy).to_string ());
|
||||
|
||||
} else if (mp_width->hasFocus ()) {
|
||||
|
||||
double w = 0.0;
|
||||
tl::from_string (tl::to_string (mp_width->text ()), w);
|
||||
|
||||
// NOTE: going the way through "configure" makes the width part of the recent path configuration
|
||||
dispatcher->config_set (cfg_edit_path_width, tl::to_string (w));
|
||||
|
||||
}
|
||||
|
||||
} catch (...) {
|
||||
}
|
||||
|
||||
m_in_commit = false;
|
||||
}
|
||||
|
||||
void
|
||||
PathConnectionToolboxWidget::configure (const std::string &name, const std::string &value)
|
||||
{
|
||||
if (name == ShapeEditService::connection_configure_name () &&
|
||||
((! mp_x_le->hasFocus () && ! mp_y_le->hasFocus ()) || m_in_commit)) {
|
||||
|
||||
try {
|
||||
|
||||
db::DVector mv;
|
||||
tl::from_string (value, mv);
|
||||
|
||||
mp_x_le->setText (tl::to_qstring (tl::micron_to_string (mv.x ())));
|
||||
mp_y_le->setText (tl::to_qstring (tl::micron_to_string (mv.y ())));
|
||||
|
||||
} catch (...) {
|
||||
}
|
||||
|
||||
} else if (name == cfg_edit_path_width &&
|
||||
(! mp_width->hasFocus () || m_in_commit)) {
|
||||
|
||||
try {
|
||||
|
||||
double w = 0.0;
|
||||
tl::from_string (value, w);
|
||||
|
||||
mp_width->setText (tl::to_qstring (tl::micron_to_string (w)));
|
||||
|
||||
} catch (...) {
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------
|
||||
// Connections toolbox widget (for texts)
|
||||
|
||||
TextToolboxWidget::TextToolboxWidget (lay::LayoutViewBase *view, lay::Dispatcher *dispatcher)
|
||||
: lay::EditorOptionsPageWidget (view, dispatcher), m_in_commit (false)
|
||||
{
|
||||
mp_layout = new QHBoxLayout (this);
|
||||
|
||||
mp_text = new lay::DecoratedLineEdit (this);
|
||||
mp_text->set_label ("l:");
|
||||
mp_layout->addWidget (mp_text);
|
||||
|
||||
mp_layout->addStretch (1);
|
||||
|
||||
hide ();
|
||||
|
||||
set_toolbox_widget (true);
|
||||
set_transparent (true);
|
||||
}
|
||||
|
||||
TextToolboxWidget::~TextToolboxWidget ()
|
||||
{
|
||||
// .. nothing yet ..
|
||||
}
|
||||
|
||||
std::string
|
||||
TextToolboxWidget::title () const
|
||||
{
|
||||
return "Text Options";
|
||||
}
|
||||
|
||||
void
|
||||
TextToolboxWidget::deactivated ()
|
||||
{
|
||||
hide ();
|
||||
}
|
||||
|
||||
void
|
||||
TextToolboxWidget::commit (lay::Dispatcher *dispatcher)
|
||||
{
|
||||
m_in_commit = true;
|
||||
|
||||
try {
|
||||
dispatcher->config_set (cfg_edit_text_string, tl::to_string (mp_text->text ()));
|
||||
} catch (...) {
|
||||
}
|
||||
|
||||
m_in_commit = false;
|
||||
}
|
||||
|
||||
void
|
||||
TextToolboxWidget::configure (const std::string &name, const std::string &value)
|
||||
{
|
||||
if (name == cfg_edit_text_string && (! mp_text->hasFocus () || m_in_commit)) {
|
||||
mp_text->setText (tl::to_qstring (value));
|
||||
}
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------
|
||||
// Registrations
|
||||
|
||||
// unspecific editor options - used for all plugins that want it
|
||||
static tl::RegisteredClass<lay::EditorOptionsPageFactoryBase> s_factory_generic (new lay::EditorOptionsPageFactory<EditorOptionsGeneric> ("GenericEditorOptions"), 0);
|
||||
|
||||
static tl::RegisteredClass<lay::EditorOptionsPageFactoryBase> s_factory_texts (new lay::EditorOptionsPageFactory<edt::EditorOptionsText> ("edt::Service(Texts)"), 0);
|
||||
static tl::RegisteredClass<lay::EditorOptionsPageFactoryBase> s_factory_paths (new lay::EditorOptionsPageFactory<edt::EditorOptionsPath> ("edt::Service(Paths)"), 0);
|
||||
static tl::RegisteredClass<lay::EditorOptionsPageFactoryBase> s_factory_insts (new lay::EditorOptionsPageFactory<edt::EditorOptionsInstPCellParam> ("edt::Service(CellInstances)"), 0);
|
||||
static tl::RegisteredClass<lay::EditorOptionsPageFactoryBase> s_factory_insts_pcell (new lay::EditorOptionsPageFactory<edt::EditorOptionsInst> ("edt::Service(CellInstances)"), 0);
|
||||
|
||||
// toolkit widgets
|
||||
static tl::RegisteredClass<lay::EditorOptionsPageFactoryBase> s_box_tookit_widget_factory (new lay::EditorOptionsPageFactory<BoxToolboxWidget> ("edt::Service(Boxes)"), 0);
|
||||
static tl::RegisteredClass<lay::EditorOptionsPageFactoryBase> s_path_connection_tookit_widget_factory (new lay::EditorOptionsPageFactory<PathConnectionToolboxWidget> ("edt::Service(Paths)"), 0);
|
||||
static tl::RegisteredClass<lay::EditorOptionsPageFactoryBase> s_connection_tookit_widget_factory_polygons (new lay::EditorOptionsPageFactory<ConnectionToolboxWidget> ("edt::Service(Polygons)"), 0);
|
||||
static tl::RegisteredClass<lay::EditorOptionsPageFactoryBase> s_text_tookit_widget_factory (new lay::EditorOptionsPageFactory<TextToolboxWidget> ("edt::Service(Texts)"), 0);
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
|
|
|
|||
|
|
@ -26,6 +26,7 @@
|
|||
#define HDR_edtEditorOptionsPages
|
||||
|
||||
#include "layEditorOptionsPage.h"
|
||||
#include "layEditorOptionsPageWidget.h"
|
||||
|
||||
#include <tlVariant.h>
|
||||
|
||||
|
|
@ -35,6 +36,7 @@
|
|||
|
||||
class QTabWidget;
|
||||
class QLabel;
|
||||
class QHBoxLayout;
|
||||
|
||||
namespace Ui
|
||||
{
|
||||
|
|
@ -50,10 +52,10 @@ namespace Ui
|
|||
|
||||
namespace lay
|
||||
{
|
||||
class PluginDeclaration;
|
||||
class Dispatcher;
|
||||
class LayoutViewBase;
|
||||
class Plugin;
|
||||
class DecoratedLineEdit;
|
||||
}
|
||||
|
||||
namespace edt
|
||||
|
|
@ -65,7 +67,7 @@ class PCellParametersPage;
|
|||
* @brief The generic properties page
|
||||
*/
|
||||
class EditorOptionsGeneric
|
||||
: public lay::EditorOptionsPage
|
||||
: public lay::EditorOptionsPageWidget
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
|
|
@ -74,7 +76,7 @@ public:
|
|||
~EditorOptionsGeneric ();
|
||||
|
||||
virtual std::string title () const;
|
||||
virtual int order () const { return 0; }
|
||||
virtual int order () const { return -10; }
|
||||
void apply (lay::Dispatcher *root);
|
||||
void setup (lay::Dispatcher *root);
|
||||
|
||||
|
|
@ -90,14 +92,14 @@ private:
|
|||
* @brief The text properties page
|
||||
*/
|
||||
class EditorOptionsText
|
||||
: public lay::EditorOptionsPage
|
||||
: public lay::EditorOptionsPageWidget
|
||||
{
|
||||
public:
|
||||
EditorOptionsText (lay::LayoutViewBase *view, lay::Dispatcher *dispatcher);
|
||||
~EditorOptionsText ();
|
||||
|
||||
virtual std::string title () const;
|
||||
virtual int order () const { return 10; }
|
||||
virtual int order () const { return 0; }
|
||||
void apply (lay::Dispatcher *root);
|
||||
void setup (lay::Dispatcher *root);
|
||||
|
||||
|
|
@ -109,7 +111,7 @@ private:
|
|||
* @brief The path properties page
|
||||
*/
|
||||
class EditorOptionsPath
|
||||
: public lay::EditorOptionsPage
|
||||
: public lay::EditorOptionsPageWidget
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
|
|
@ -118,7 +120,7 @@ public:
|
|||
~EditorOptionsPath ();
|
||||
|
||||
virtual std::string title () const;
|
||||
virtual int order () const { return 30; }
|
||||
virtual int order () const { return 0; }
|
||||
void apply (lay::Dispatcher *root);
|
||||
void setup (lay::Dispatcher *root);
|
||||
|
||||
|
|
@ -133,7 +135,7 @@ private:
|
|||
* @brief The instance properties page
|
||||
*/
|
||||
class EditorOptionsInst
|
||||
: public lay::EditorOptionsPage
|
||||
: public lay::EditorOptionsPageWidget
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
|
|
@ -142,7 +144,7 @@ public:
|
|||
~EditorOptionsInst ();
|
||||
|
||||
virtual std::string title () const;
|
||||
virtual int order () const { return 20; }
|
||||
virtual int order () const { return 0; }
|
||||
void apply (lay::Dispatcher *root);
|
||||
void setup (lay::Dispatcher *root);
|
||||
|
||||
|
|
@ -165,7 +167,7 @@ private:
|
|||
* @brief The instance properties page (PCell parameters)
|
||||
*/
|
||||
class EditorOptionsInstPCellParam
|
||||
: public lay::EditorOptionsPage
|
||||
: public lay::EditorOptionsPageWidget
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
|
|
@ -174,7 +176,7 @@ public:
|
|||
~EditorOptionsInstPCellParam ();
|
||||
|
||||
virtual std::string title () const;
|
||||
virtual int order () const { return 21; }
|
||||
virtual int order () const { return 1; }
|
||||
void apply (lay::Dispatcher *root);
|
||||
void setup (lay::Dispatcher *root);
|
||||
|
||||
|
|
@ -192,6 +194,101 @@ private:
|
|||
virtual void technology_changed (const std::string &);
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief The toolbox widget for boxes
|
||||
*/
|
||||
class BoxToolboxWidget
|
||||
: public lay::EditorOptionsPageWidget
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
BoxToolboxWidget (lay::LayoutViewBase *view, lay::Dispatcher *dispatcher);
|
||||
~BoxToolboxWidget ();
|
||||
|
||||
virtual std::string title () const;
|
||||
virtual int order () const { return 200; }
|
||||
virtual void configure (const std::string &name, const std::string &value);
|
||||
virtual void commit (lay::Dispatcher *root);
|
||||
virtual void deactivated ();
|
||||
|
||||
private:
|
||||
QHBoxLayout *mp_layout;
|
||||
lay::DecoratedLineEdit *mp_x_le, *mp_y_le;
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief The toolbox widget for connections (polygon edges)
|
||||
*/
|
||||
class ConnectionToolboxWidget
|
||||
: public lay::EditorOptionsPageWidget
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
ConnectionToolboxWidget (lay::LayoutViewBase *view, lay::Dispatcher *dispatcher);
|
||||
~ConnectionToolboxWidget ();
|
||||
|
||||
virtual std::string title () const;
|
||||
virtual int order () const { return 200; }
|
||||
virtual void configure (const std::string &name, const std::string &value);
|
||||
virtual void commit (lay::Dispatcher *root);
|
||||
virtual void deactivated ();
|
||||
|
||||
private:
|
||||
QHBoxLayout *mp_layout;
|
||||
lay::DecoratedLineEdit *mp_x_le, *mp_y_le;
|
||||
bool m_in_commit;
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief The toolbox widget for connections (path segments)
|
||||
*/
|
||||
class PathConnectionToolboxWidget
|
||||
: public lay::EditorOptionsPageWidget
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
PathConnectionToolboxWidget (lay::LayoutViewBase *view, lay::Dispatcher *dispatcher);
|
||||
~PathConnectionToolboxWidget ();
|
||||
|
||||
virtual std::string title () const;
|
||||
virtual int order () const { return 200; }
|
||||
virtual void configure (const std::string &name, const std::string &value);
|
||||
virtual void commit (lay::Dispatcher *root);
|
||||
virtual void deactivated ();
|
||||
|
||||
private:
|
||||
QHBoxLayout *mp_layout;
|
||||
lay::DecoratedLineEdit *mp_x_le, *mp_y_le, *mp_width;
|
||||
bool m_in_commit;
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief The toolbox widget for texts
|
||||
*/
|
||||
class TextToolboxWidget
|
||||
: public lay::EditorOptionsPageWidget
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
TextToolboxWidget (lay::LayoutViewBase *view, lay::Dispatcher *dispatcher);
|
||||
~TextToolboxWidget ();
|
||||
|
||||
virtual std::string title () const;
|
||||
virtual int order () const { return 200; }
|
||||
virtual void configure (const std::string &name, const std::string &value);
|
||||
virtual void commit (lay::Dispatcher *root);
|
||||
virtual void deactivated ();
|
||||
|
||||
private:
|
||||
QHBoxLayout *mp_layout;
|
||||
lay::DecoratedLineEdit *mp_text;
|
||||
bool m_in_commit;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
|
|
|
|||
|
|
@ -226,7 +226,7 @@ BEGIN_PROTECTED
|
|||
layout = &cv->layout ();
|
||||
}
|
||||
|
||||
lay::LibraryCellSelectionForm form (this, layout, "browse_lib_cell", false, lib != 0 /*for libs show top cells only*/);
|
||||
lay::LibraryCellSelectionForm form (this, layout, "browse_lib_cell", false, lib != 0 /*for libs show top cells only*/, lib != 0 /*for libs hide private cells*/);
|
||||
if (lib) {
|
||||
form.setWindowTitle (tl::to_qstring (tl::to_string (QObject::tr ("Select Cell - Library: ")) + lib->get_description ()));
|
||||
}
|
||||
|
|
|
|||
|
|
@ -417,7 +417,7 @@ InstService::do_mouse_click (const db::DPoint &p)
|
|||
}
|
||||
|
||||
void
|
||||
InstService::do_finish_edit ()
|
||||
InstService::do_finish_edit (bool /*accept*/)
|
||||
{
|
||||
try {
|
||||
|
||||
|
|
|
|||
|
|
@ -53,7 +53,7 @@ public:
|
|||
virtual void do_mouse_move (const db::DPoint &p);
|
||||
virtual bool do_mouse_click (const db::DPoint &p);
|
||||
virtual void do_mouse_transform (const db::DPoint &p, db::DFTrans trans);
|
||||
virtual void do_finish_edit ();
|
||||
virtual void do_finish_edit (bool accept);
|
||||
virtual void do_cancel_edit ();
|
||||
virtual bool do_activated ();
|
||||
#if defined(HAVE_QT)
|
||||
|
|
|
|||
|
|
@ -133,6 +133,13 @@ MoveTrackerService::end_move (const db::DPoint & /*p*/, lay::angle_constraint_ty
|
|||
move_cancel (); // formally this functionality fits here
|
||||
}
|
||||
|
||||
void
|
||||
MoveTrackerService::end_move (const db::DVector & /*v*/)
|
||||
{
|
||||
call_editor_hooks (m_editor_hooks, &edt::EditorHooks::commit_edit);
|
||||
move_cancel (); // formally this functionality fits here
|
||||
}
|
||||
|
||||
void
|
||||
MoveTrackerService::edit_cancel ()
|
||||
{
|
||||
|
|
|
|||
|
|
@ -68,6 +68,11 @@ public:
|
|||
*/
|
||||
virtual void end_move (const db::DPoint &p, lay::angle_constraint_type ac);
|
||||
|
||||
/**
|
||||
* @brief Terminate a "move" operation with compulsory move vector
|
||||
*/
|
||||
virtual void end_move (const db::DVector &v);
|
||||
|
||||
/**
|
||||
* @brief Access to the view object
|
||||
*/
|
||||
|
|
|
|||
|
|
@ -26,6 +26,7 @@
|
|||
#include "laySnap.h"
|
||||
#include "layFinder.h"
|
||||
#include "layConverters.h"
|
||||
#include "layMove.h"
|
||||
#include "tlProgress.h"
|
||||
#include "edtPartialService.h"
|
||||
#include "edtService.h"
|
||||
|
|
@ -1096,7 +1097,7 @@ PartialService::PartialService (db::Manager *manager, lay::LayoutViewBase *view,
|
|||
db::Object (manager),
|
||||
mp_view (view),
|
||||
mp_root (root),
|
||||
m_dragging (false),
|
||||
m_moving (false),
|
||||
m_keep_selection (true),
|
||||
mp_box (0),
|
||||
m_color (0),
|
||||
|
|
@ -1406,15 +1407,6 @@ PartialService::snap (const db::DVector &v_org) const
|
|||
}
|
||||
}
|
||||
|
||||
const int sr_pixels = 8; // TODO: make variable
|
||||
|
||||
lay::PointSnapToObjectResult
|
||||
PartialService::snap2 (const db::DPoint &p) const
|
||||
{
|
||||
double snap_range = ui ()->mouse_event_trans ().inverted ().ctrans (sr_pixels);
|
||||
return lay::obj_snap (m_snap_to_objects ? view () : 0, m_start, p, m_edit_grid == db::DVector () ? m_global_grid : m_edit_grid, move_ac (), snap_range);
|
||||
}
|
||||
|
||||
void
|
||||
PartialService::transform (const db::DCplxTrans &tr)
|
||||
{
|
||||
|
|
@ -1769,7 +1761,7 @@ void
|
|||
PartialService::edit_cancel ()
|
||||
{
|
||||
// stop dragging, clear selection
|
||||
m_dragging = false;
|
||||
m_moving = false;
|
||||
|
||||
if (mp_box) {
|
||||
delete mp_box;
|
||||
|
|
@ -1790,74 +1782,85 @@ PartialService::wheel_event (int /*delta*/, bool /*horizontal*/, const db::DPoin
|
|||
return false;
|
||||
}
|
||||
|
||||
bool
|
||||
PartialService::mouse_move_event (const db::DPoint &p, unsigned int buttons, bool prio)
|
||||
const int sr_pixels = 8; // TODO: make variable
|
||||
|
||||
void
|
||||
PartialService::move_impl (const db::DPoint &p)
|
||||
{
|
||||
clear_mouse_cursors ();
|
||||
// drag the vertex or edge/segment
|
||||
if (is_single_point_selection () || is_single_edge_selection ()) {
|
||||
|
||||
if (m_dragging) {
|
||||
lay::PointSnapToObjectResult snap_details;
|
||||
|
||||
set_cursor (lay::Cursor::size_all);
|
||||
// for a single selected point or edge, m_start is the original position and we snap the target -
|
||||
// thus, we can bring the point on grid or to an object's edge or vertex
|
||||
double snap_range = ui ()->mouse_event_trans ().inverted ().ctrans (sr_pixels);
|
||||
snap_details = lay::obj_snap (m_snap_to_objects ? view () : 0, m_start, p, m_edit_grid == db::DVector () ? m_global_grid : m_edit_grid, lay::AC_Any, snap_range);;
|
||||
|
||||
m_alt_ac = lay::ac_from_buttons (buttons);
|
||||
if (snap_details.object_snap == lay::PointSnapToObjectResult::NoObject) {
|
||||
|
||||
// drag the vertex or edge/segment
|
||||
if (is_single_point_selection () || is_single_edge_selection ()) {
|
||||
|
||||
lay::PointSnapToObjectResult snap_details;
|
||||
|
||||
// for a single selected point or edge, m_start is the original position and we snap the target -
|
||||
// thus, we can bring the point on grid or to an object's edge or vertex
|
||||
snap_details = snap2 (p);
|
||||
|
||||
if (snap_details.object_snap == lay::PointSnapToObjectResult::NoObject) {
|
||||
|
||||
m_current = m_start + snap_move (p - m_start);
|
||||
|
||||
} else {
|
||||
|
||||
auto snapped_to_object = snap_details.snapped_point;
|
||||
m_current = snapped_to_object;
|
||||
|
||||
if (snap_details.object_snap != lay::PointSnapToObjectResult::ObjectVertex) {
|
||||
// snap to grid on longer side of reference edge and to object on shorter
|
||||
auto snapped_to_object_and_grid = m_start + snap_move (snapped_to_object - m_start);
|
||||
if (std::abs (snap_details.object_ref.dx ()) > std::abs (snap_details.object_ref.dy ())) {
|
||||
m_current.set_x (snapped_to_object_and_grid.x ());
|
||||
// project to edge, so we always hit it
|
||||
auto cp = snap_details.object_ref.cut_point (db::DEdge (m_current, m_current + db::DVector (0, 1.0)));
|
||||
if (cp.first) {
|
||||
m_current.set_y (cp.second.y ());
|
||||
}
|
||||
} else if (std::abs (snap_details.object_ref.dy ()) > std::abs (snap_details.object_ref.dx ())) {
|
||||
m_current.set_y (snapped_to_object_and_grid.y ());
|
||||
// project to edge, so we always hit it
|
||||
auto cp = snap_details.object_ref.cut_point (db::DEdge (m_current, m_current + db::DVector (1.0, 0)));
|
||||
if (cp.first) {
|
||||
m_current.set_x (cp.second.x ());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
mouse_cursor_from_snap_details (snap_details);
|
||||
|
||||
}
|
||||
m_current = m_start + snap_move (p - m_start);
|
||||
|
||||
} else {
|
||||
|
||||
// snap movement to angle and grid without object
|
||||
m_current = m_start + snap_move (p - m_start);
|
||||
clear_mouse_cursors ();
|
||||
auto snapped_to_object = snap_details.snapped_point;
|
||||
m_current = snapped_to_object;
|
||||
|
||||
if (snap_details.object_snap != lay::PointSnapToObjectResult::ObjectVertex) {
|
||||
|
||||
// snap to grid on longer side of reference edge and to object on shorter
|
||||
auto snapped_to_object_and_grid = m_start + snap_move (snapped_to_object - m_start);
|
||||
if (std::abs (snap_details.object_ref.dx ()) > std::abs (snap_details.object_ref.dy ())) {
|
||||
m_current.set_x (snapped_to_object_and_grid.x ());
|
||||
// project to edge, so we always hit it
|
||||
auto cp = snap_details.object_ref.cut_point (db::DEdge (m_current, m_current + db::DVector (0, 1.0)));
|
||||
if (cp.first) {
|
||||
m_current.set_y (cp.second.y ());
|
||||
}
|
||||
} else if (std::abs (snap_details.object_ref.dy ()) > std::abs (snap_details.object_ref.dx ())) {
|
||||
m_current.set_y (snapped_to_object_and_grid.y ());
|
||||
// project to edge, so we always hit it
|
||||
auto cp = snap_details.object_ref.cut_point (db::DEdge (m_current, m_current + db::DVector (1.0, 0)));
|
||||
if (cp.first) {
|
||||
m_current.set_x (cp.second.x ());
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
mouse_cursor_from_snap_details (snap_details);
|
||||
|
||||
}
|
||||
|
||||
selection_to_view ();
|
||||
if (is_single_edge_selection ()) {
|
||||
|
||||
call_editor_hooks (m_editor_hooks, &edt::EditorHooks::begin_edits);
|
||||
issue_editor_hook_calls (m_editor_hooks);
|
||||
call_editor_hooks (m_editor_hooks, &edt::EditorHooks::end_edits);
|
||||
// in case of edge movement, project the move vector to the edge normal -
|
||||
// that is cosmetic, so we don't imply a lateral shift
|
||||
auto e = single_selected_edge ().d ();
|
||||
if (e.double_length () > db::epsilon) {
|
||||
db::DVector n = db::DVector (e.y (), -e.x ()) * (1.0 / e.double_length ());
|
||||
m_current = m_start + n * db::sprod (m_current - m_start, n);
|
||||
}
|
||||
|
||||
m_alt_ac = lay::AC_Global;
|
||||
}
|
||||
|
||||
} else {
|
||||
|
||||
// snap movement to angle and grid without object
|
||||
m_current = m_start + snap_move (p - m_start);
|
||||
|
||||
}
|
||||
|
||||
selection_to_view ();
|
||||
}
|
||||
|
||||
bool
|
||||
PartialService::mouse_move_event (const db::DPoint &p, unsigned int buttons, bool prio)
|
||||
{
|
||||
if (m_moving) {
|
||||
|
||||
// event is handled by the move service
|
||||
return false;
|
||||
|
||||
} else if (prio) {
|
||||
|
||||
|
|
@ -1916,9 +1919,9 @@ PartialService::mouse_press_event (const db::DPoint &p, unsigned int buttons, bo
|
|||
return false;
|
||||
}
|
||||
|
||||
if (m_dragging) {
|
||||
if (m_moving) {
|
||||
|
||||
// eat events if already dragging
|
||||
// eat events if moving -> handled by move service
|
||||
return true;
|
||||
|
||||
} else if (! mp_box) {
|
||||
|
|
@ -1964,25 +1967,8 @@ PartialService::mouse_press_event (const db::DPoint &p, unsigned int buttons, bo
|
|||
|
||||
} else {
|
||||
|
||||
// something was selected: start dragging this ..
|
||||
m_dragging = true;
|
||||
m_keep_selection = true;
|
||||
|
||||
if (is_single_point_selection ()) {
|
||||
// for a single selected point we use the original point as the start location which
|
||||
// allows bringing it to grid
|
||||
m_current = m_start = single_selected_point ();
|
||||
} else if (is_single_edge_selection ()) {
|
||||
// for an edge selection use the point projected to edge as the start location which
|
||||
// allows bringing it to grid
|
||||
m_current = m_start = projected_to_edge (single_selected_edge (), p);
|
||||
} else {
|
||||
m_current = m_start = p;
|
||||
}
|
||||
|
||||
ui ()->grab_mouse (this, true);
|
||||
|
||||
open_editor_hooks ();
|
||||
// delegate further actions to move service, which will start a move operation
|
||||
mp_view->move_service ()->start_move ();
|
||||
|
||||
}
|
||||
|
||||
|
|
@ -2014,43 +2000,9 @@ PartialService::mouse_click_event (const db::DPoint &p, unsigned int buttons, bo
|
|||
return false;
|
||||
}
|
||||
|
||||
if (m_dragging) {
|
||||
if (m_moving) {
|
||||
|
||||
m_alt_ac = lay::ac_from_buttons (buttons);
|
||||
|
||||
if (m_current != m_start) {
|
||||
|
||||
// stop dragging
|
||||
ui ()->ungrab_mouse (this);
|
||||
|
||||
if (manager ()) {
|
||||
manager ()->transaction (tl::to_string (tr ("Partial move")));
|
||||
}
|
||||
|
||||
// heuristically, if there is just one edge selected: do not confine to the movement
|
||||
// angle constraint - the edge usually is confined enough
|
||||
db::DTrans move_trans = db::DTrans (m_current - m_start);
|
||||
|
||||
transform_selection (move_trans);
|
||||
|
||||
if (manager ()) {
|
||||
manager ()->commit ();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
if (! m_keep_selection) {
|
||||
m_selection.clear ();
|
||||
}
|
||||
|
||||
m_dragging = false;
|
||||
selection_to_view ();
|
||||
|
||||
close_editor_hooks (true);
|
||||
|
||||
m_alt_ac = lay::AC_Global;
|
||||
|
||||
return true;
|
||||
return false;
|
||||
|
||||
} else if (ui ()->mouse_event_viewport ().contains (p)) {
|
||||
|
||||
|
|
@ -2143,26 +2095,16 @@ PartialService::mouse_click_event (const db::DPoint &p, unsigned int buttons, bo
|
|||
|
||||
}
|
||||
|
||||
// start dragging with that single selection
|
||||
// start dragging with the selection
|
||||
if (mode == lay::Editable::Replace && ! m_selection.empty ()) {
|
||||
|
||||
m_dragging = true;
|
||||
// delegate further actions to move service, which will start a move operation
|
||||
mp_view->move_service ()->start_move ();
|
||||
|
||||
// modify the decision to keep the selection (needs to come after the
|
||||
// move service called begin_move)
|
||||
m_keep_selection = ! new_selection;
|
||||
|
||||
if (is_single_point_selection ()) {
|
||||
// for a single selected point we use the original point as the start location which
|
||||
// allows bringing it to grid
|
||||
m_current = m_start = single_selected_point ();
|
||||
} else if (is_single_edge_selection ()) {
|
||||
// for an edge selection use the point projected to edge as the start location which
|
||||
// allows bringing it to grid
|
||||
m_current = m_start = projected_to_edge (single_selected_edge (), p);
|
||||
} else {
|
||||
m_current = m_start = p;
|
||||
}
|
||||
|
||||
open_editor_hooks ();
|
||||
|
||||
}
|
||||
|
||||
selection_to_view ();
|
||||
|
|
@ -2197,10 +2139,6 @@ PartialService::mouse_double_click_event (const db::DPoint &p, unsigned int butt
|
|||
|
||||
close_editor_hooks (false);
|
||||
|
||||
// stop dragging
|
||||
ui ()->ungrab_mouse (this);
|
||||
m_dragging = false;
|
||||
|
||||
partial_select (db::DBox (p, p), lay::Editable::Replace);
|
||||
|
||||
if (! m_selection.empty ()) {
|
||||
|
|
@ -2345,6 +2283,17 @@ PartialService::mouse_release_event (const db::DPoint &p, unsigned int buttons,
|
|||
return false;
|
||||
}
|
||||
|
||||
bool
|
||||
PartialService::key_event (unsigned int key, unsigned int buttons)
|
||||
{
|
||||
if (m_moving && buttons == 0 && (key == lay::KeyEnter || key == lay::KeyReturn)) {
|
||||
mp_view->move_service ()->end_move ();
|
||||
return true;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
bool
|
||||
PartialService::begin_move (MoveMode mode, const db::DPoint &p, lay::angle_constraint_type ac)
|
||||
{
|
||||
|
|
@ -2352,7 +2301,7 @@ PartialService::begin_move (MoveMode mode, const db::DPoint &p, lay::angle_const
|
|||
|
||||
m_alt_ac = ac;
|
||||
|
||||
m_dragging = true;
|
||||
m_moving = true;
|
||||
m_keep_selection = true;
|
||||
|
||||
if (is_single_point_selection ()) {
|
||||
|
|
@ -2432,7 +2381,7 @@ PartialService::snap_marker_to_grid (const db::DVector &v, bool &snapped) const
|
|||
|
||||
if (snapped) {
|
||||
vr += vv;
|
||||
return db::DVector (vr.x () * snapped_to.x (), vr.y () * snapped_to.y ());
|
||||
return db::DVector (vr.x () * fabs (snapped_to.x ()), vr.y () * fabs (snapped_to.y ()));
|
||||
} else {
|
||||
return db::DVector ();
|
||||
}
|
||||
|
|
@ -2452,62 +2401,42 @@ PartialService::snap_move (const db::DVector &v) const
|
|||
void
|
||||
PartialService::move (const db::DPoint &p, lay::angle_constraint_type ac)
|
||||
{
|
||||
if (! m_dragging) {
|
||||
if (! m_moving) {
|
||||
return;
|
||||
}
|
||||
|
||||
m_alt_ac = ac;
|
||||
|
||||
set_cursor (lay::Cursor::size_all);
|
||||
clear_mouse_cursors ();
|
||||
|
||||
// drag the vertex or edge/segment
|
||||
if (is_single_point_selection () || is_single_edge_selection ()) {
|
||||
move_impl (p);
|
||||
|
||||
lay::PointSnapToObjectResult snap_details;
|
||||
|
||||
// for a single selected point or edge, m_start is the original position and we snap the target -
|
||||
// thus, we can bring the point on grid or to an object's edge or vertex
|
||||
snap_details = snap2 (p);
|
||||
if (snap_details.object_snap == lay::PointSnapToObjectResult::NoObject) {
|
||||
m_current = m_start + snap_move (p - m_start);
|
||||
} else {
|
||||
m_current = snap_details.snapped_point;
|
||||
mouse_cursor_from_snap_details (snap_details);
|
||||
}
|
||||
|
||||
} else {
|
||||
|
||||
// snap movement to angle and grid without object
|
||||
m_current = m_start + snap_move (p - m_start);
|
||||
clear_mouse_cursors ();
|
||||
|
||||
}
|
||||
|
||||
selection_to_view ();
|
||||
propose_move_transformation (db::DTrans (m_current - m_start), 0);
|
||||
|
||||
m_alt_ac = lay::AC_Global;
|
||||
}
|
||||
|
||||
void
|
||||
PartialService::end_move (const db::DPoint & /*p*/, lay::angle_constraint_type ac)
|
||||
PartialService::end_move (const db::DVector &v)
|
||||
{
|
||||
if (! m_dragging) {
|
||||
m_current = m_start + v;
|
||||
end_move (db::DPoint (), lay::AC_Any);
|
||||
}
|
||||
|
||||
void
|
||||
PartialService::end_move (const db::DPoint & /*p*/, lay::angle_constraint_type /*ac*/)
|
||||
{
|
||||
if (! m_moving) {
|
||||
return;
|
||||
}
|
||||
|
||||
m_alt_ac = ac;
|
||||
|
||||
if (m_current != m_start) {
|
||||
|
||||
// stop dragging
|
||||
ui ()->ungrab_mouse (this);
|
||||
|
||||
if (manager ()) {
|
||||
manager ()->transaction (tl::to_string (tr ("Partial move")));
|
||||
}
|
||||
|
||||
// heuristically, if there is just one edge selected: do not confine to the movement
|
||||
// angle constraint - the edge usually is confined enough
|
||||
db::DTrans move_trans = db::DTrans (m_current - m_start);
|
||||
|
||||
transform_selection (move_trans);
|
||||
|
|
@ -2522,7 +2451,7 @@ PartialService::end_move (const db::DPoint & /*p*/, lay::angle_constraint_type a
|
|||
m_selection.clear ();
|
||||
}
|
||||
|
||||
m_dragging = false;
|
||||
m_moving = false;
|
||||
selection_to_view ();
|
||||
|
||||
clear_mouse_cursors ();
|
||||
|
|
@ -2608,9 +2537,6 @@ PartialService::del ()
|
|||
{
|
||||
std::set<db::Layout *> needs_cleanup;
|
||||
|
||||
// stop dragging
|
||||
ui ()->ungrab_mouse (this);
|
||||
|
||||
std::map <std::pair <db::cell_index_type, std::pair <unsigned int, unsigned int> >, std::vector <partial_objects::const_iterator> > shapes_to_delete_by_cell;
|
||||
|
||||
for (partial_objects::iterator r = m_selection.begin (); r != m_selection.end (); ++r) {
|
||||
|
|
@ -2703,7 +2629,6 @@ PartialService::del ()
|
|||
handle_guiding_shape_changes ();
|
||||
|
||||
m_selection.clear ();
|
||||
m_dragging = false;
|
||||
selection_to_view ();
|
||||
|
||||
close_editor_hooks (false);
|
||||
|
|
@ -3008,22 +2933,8 @@ PartialService::do_selection_to_view ()
|
|||
{
|
||||
// if dragging, establish the current displacement
|
||||
db::DTrans move_trans;
|
||||
if (m_dragging) {
|
||||
|
||||
// heuristically, if there is just one edge selected: do not confine to the movement
|
||||
// angle constraint - the edge usually is confined enough
|
||||
if (m_selection.size () == 1 && ! m_selection.begin ()->first.is_cell_inst () && m_selection.begin ()->second.size () == 3 /*p1,p2,edge*/) {
|
||||
move_trans = db::DTrans (m_current - m_start);
|
||||
} else {
|
||||
// TODO: DTrans should have a ctor that takes a vector
|
||||
move_trans = db::DTrans (lay::snap_angle (m_current - m_start, move_ac ()));
|
||||
}
|
||||
|
||||
// display vector
|
||||
view ()->message (std::string ("dx: ") + tl::micron_to_string (move_trans.disp ().x ()) +
|
||||
std::string (" dy: ") + tl::micron_to_string (move_trans.disp ().y ()) +
|
||||
std::string (" d: ") + tl::micron_to_string (move_trans.disp ().length ()));
|
||||
|
||||
if (m_moving) {
|
||||
move_trans = db::DTrans (m_current - m_start);
|
||||
}
|
||||
|
||||
size_t n_marker = 0;
|
||||
|
|
@ -3065,7 +2976,7 @@ PartialService::do_selection_to_view ()
|
|||
std::map <EdgeWithIndex, db::Edge> new_edges;
|
||||
std::map <PointWithIndex, db::Point> new_points;
|
||||
|
||||
if (m_dragging) {
|
||||
if (m_moving) {
|
||||
create_shift_sets (r->first.shape (), r->second, new_points, new_edges, move_vector);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -234,6 +234,11 @@ public:
|
|||
*/
|
||||
virtual bool mouse_release_event (const db::DPoint &p, unsigned int buttons, bool prio);
|
||||
|
||||
/**
|
||||
* @brief Key handling event
|
||||
*/
|
||||
virtual bool key_event (unsigned int key, unsigned int buttons);
|
||||
|
||||
/**
|
||||
* @brief Transforms the selection
|
||||
*
|
||||
|
|
@ -287,6 +292,11 @@ public:
|
|||
*/
|
||||
virtual void end_move (const db::DPoint &p, lay::angle_constraint_type ac);
|
||||
|
||||
/**
|
||||
* @brief Terminate a "move" operation with compulsory move vector
|
||||
*/
|
||||
virtual void end_move (const db::DVector &v);
|
||||
|
||||
/**
|
||||
* @brief Implement the "select" method at least to clear the selection
|
||||
*/
|
||||
|
|
@ -335,7 +345,7 @@ private:
|
|||
// The layout view that this service is attached to
|
||||
lay::LayoutViewBase *mp_view;
|
||||
lay::Dispatcher *mp_root;
|
||||
bool m_dragging;
|
||||
bool m_moving;
|
||||
bool m_keep_selection;
|
||||
db::DPoint m_start, m_current;
|
||||
db::DPoint m_p1, m_p2;
|
||||
|
|
@ -381,10 +391,10 @@ private:
|
|||
|
||||
db::DPoint snap (const db::DPoint &p) const;
|
||||
db::DVector snap (const db::DVector &p) const;
|
||||
lay::PointSnapToObjectResult snap2 (const db::DPoint &p) const;
|
||||
void update_vector_snapped_point (const db::DPoint &pt, db::DVector &vr, bool &result_set) const;
|
||||
db::DVector snap_marker_to_grid (const db::DVector &v, bool &snapped) const;
|
||||
db::DVector snap_move(const db::DVector &p) const;
|
||||
void move_impl (const db::DPoint &p);
|
||||
|
||||
void enter_edge (const EdgeWithIndex &e, size_t &nmarker, partial_objects::const_iterator sel, const std::map <PointWithIndex, db::Point> &new_points, const std::map <EdgeWithIndex, db::Edge> &new_edges, const db::ICplxTrans >, const std::vector<db::DCplxTrans> &tv, bool transient);
|
||||
void enter_vertices (size_t &nmarker, partial_objects::const_iterator sel, const std::map <PointWithIndex, db::Point> &new_points, const std::map <EdgeWithIndex, db::Edge> &new_edges, const db::ICplxTrans >, const std::vector<db::DCplxTrans> &tv, bool transient);
|
||||
|
|
|
|||
|
|
@ -26,6 +26,7 @@
|
|||
#include "edtPropertiesPages.h"
|
||||
|
||||
#include "layLayoutViewBase.h"
|
||||
#include "layEditorOptionsPage.h"
|
||||
#include "layFinder.h"
|
||||
|
||||
namespace edt
|
||||
|
|
@ -160,13 +161,15 @@ PathService::do_delete ()
|
|||
}
|
||||
|
||||
void
|
||||
PathService::do_finish_edit ()
|
||||
PathService::do_finish_edit (bool accept)
|
||||
{
|
||||
// one point is reserved for the "current one"
|
||||
if (m_points.size () < 3) {
|
||||
// one point is reserved for the "current one" if accept is false
|
||||
if (! accept && ! m_points.empty ()) {
|
||||
m_points.pop_back ();
|
||||
}
|
||||
if (m_points.size () < 2) {
|
||||
throw tl::Exception (tl::to_string (tr ("A path must have at least 2 points")));
|
||||
}
|
||||
m_points.pop_back ();
|
||||
|
||||
deliver_shape (get_path ());
|
||||
|
||||
|
|
@ -175,6 +178,32 @@ PathService::do_finish_edit ()
|
|||
close_editor_hooks (true);
|
||||
}
|
||||
|
||||
void
|
||||
PathService::function (const std::string &name, const std::string &value)
|
||||
{
|
||||
if (name == ShapeEditService::connection_function_name ()) {
|
||||
|
||||
try {
|
||||
|
||||
db::DVector dim;
|
||||
tl::from_string (value, dim);
|
||||
|
||||
if (m_points.size () >= 2) {
|
||||
|
||||
m_last = m_points.back () = m_points.end () [-2] + dim;
|
||||
m_points.push_back (m_last);
|
||||
|
||||
update_marker ();
|
||||
update_via ();
|
||||
|
||||
}
|
||||
|
||||
} catch (...) {
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
PathService::update_marker ()
|
||||
{
|
||||
|
|
@ -185,12 +214,17 @@ PathService::update_marker ()
|
|||
marker->set (path, db::VCplxTrans (1.0 / layout ().dbu ()) * trans ().inverted ());
|
||||
|
||||
if (m_points.size () >= 2) {
|
||||
db::DVector dim = m_points.back () - m_points.end () [-2];
|
||||
view ()->message (std::string ("lx: ") +
|
||||
tl::micron_to_string (m_points.back ().x () - m_points.end () [-2].x ()) +
|
||||
tl::micron_to_string (dim.x ()) +
|
||||
std::string (" ly: ") +
|
||||
tl::micron_to_string (m_points.back ().y () - m_points.end () [-2].y ()) +
|
||||
tl::micron_to_string (dim.y ()) +
|
||||
std::string (" l: ") +
|
||||
tl::micron_to_string (m_points.back ().distance (m_points.end () [-2])));
|
||||
tl::micron_to_string (dim.length ()));
|
||||
auto tb = toolbox_widget ();
|
||||
if (tb) {
|
||||
tb->configure (ShapeEditService::connection_configure_name (), dim.to_string ());
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -695,6 +729,11 @@ PathService::pop_segment ()
|
|||
bool
|
||||
PathService::configure (const std::string &name, const std::string &value)
|
||||
{
|
||||
auto tb = toolbox_widget ();
|
||||
if (tb) {
|
||||
tb->configure (name, value);
|
||||
}
|
||||
|
||||
if (name == cfg_edit_path_width) {
|
||||
tl::from_string (value, m_width);
|
||||
m_needs_update = true;
|
||||
|
|
|
|||
|
|
@ -47,11 +47,12 @@ public:
|
|||
virtual bool do_mouse_click (const db::DPoint &p);
|
||||
virtual void do_mouse_move_inactive (const db::DPoint &p);
|
||||
virtual void do_delete ();
|
||||
virtual void do_finish_edit ();
|
||||
virtual void do_finish_edit (bool accept);
|
||||
virtual void do_cancel_edit ();
|
||||
virtual bool do_activated ();
|
||||
virtual void via (int dir);
|
||||
virtual bool selection_applies (const lay::ObjectInstPath &sel) const;
|
||||
virtual void function (const std::string &name, const std::string &value);
|
||||
|
||||
protected:
|
||||
bool configure (const std::string &name, const std::string &value);
|
||||
|
|
|
|||
|
|
@ -21,13 +21,9 @@
|
|||
*/
|
||||
|
||||
|
||||
#if defined(HAVE_QT)
|
||||
# include "layTipDialog.h"
|
||||
# include "layEditorOptionsPages.h"
|
||||
#endif
|
||||
|
||||
#include "layDispatcher.h"
|
||||
#include "layLayoutViewBase.h"
|
||||
#include "layEditorOptionsPage.h"
|
||||
#include "edtPlugin.h"
|
||||
#include "edtConfig.h"
|
||||
#include "edtService.h"
|
||||
|
|
@ -40,38 +36,19 @@
|
|||
#include "edtMainService.h"
|
||||
#include "edtPartialService.h"
|
||||
#include "edtMoveTrackerService.h"
|
||||
#if defined(HAVE_QT)
|
||||
# include "edtEditorOptionsPages.h"
|
||||
# include "edtRecentConfigurationPage.h"
|
||||
#endif
|
||||
#include "edtEditorOptionsPages.h"
|
||||
#include "edtRecentConfigurationPage.h"
|
||||
|
||||
#if defined(HAVE_QT)
|
||||
# include <QApplication>
|
||||
# include <QLayout>
|
||||
# include <QMessageBox>
|
||||
# include "layTipDialog.h"
|
||||
#endif
|
||||
|
||||
namespace edt
|
||||
{
|
||||
|
||||
#if defined(HAVE_QT)
|
||||
edt::RecentConfigurationPage::ConfigurationDescriptor shape_cfg_descriptors[] =
|
||||
{
|
||||
edt::RecentConfigurationPage::ConfigurationDescriptor ("", tl::to_string (tr ("Layer")), edt::RecentConfigurationPage::Layer),
|
||||
};
|
||||
#endif
|
||||
|
||||
#if defined(HAVE_QT)
|
||||
static
|
||||
void get_shape_editor_options_pages (std::vector<lay::EditorOptionsPage *> &ret, lay::LayoutViewBase *view, lay::Dispatcher *dispatcher)
|
||||
{
|
||||
ret.push_back (new RecentConfigurationPage (view, dispatcher, "edit-recent-shape-param",
|
||||
&shape_cfg_descriptors[0], &shape_cfg_descriptors[sizeof (shape_cfg_descriptors) / sizeof (shape_cfg_descriptors[0])]));
|
||||
}
|
||||
#else
|
||||
static void get_shape_editor_options_pages () { }
|
||||
#endif
|
||||
|
||||
static
|
||||
void get_text_options (std::vector < std::pair<std::string, std::string> > &options)
|
||||
{
|
||||
|
|
@ -81,27 +58,6 @@ void get_text_options (std::vector < std::pair<std::string, std::string> > &opti
|
|||
options.push_back (std::pair<std::string, std::string> (cfg_edit_text_valign, "bottom"));
|
||||
}
|
||||
|
||||
#if defined(HAVE_QT)
|
||||
static
|
||||
void get_text_editor_options_pages (std::vector<lay::EditorOptionsPage *> &ret, lay::LayoutViewBase *view, lay::Dispatcher *dispatcher)
|
||||
{
|
||||
static edt::RecentConfigurationPage::ConfigurationDescriptor text_cfg_descriptors[] =
|
||||
{
|
||||
edt::RecentConfigurationPage::ConfigurationDescriptor ("", tl::to_string (tr ("Layer")), edt::RecentConfigurationPage::Layer),
|
||||
edt::RecentConfigurationPage::ConfigurationDescriptor (cfg_edit_text_string, tl::to_string (tr ("Text")), edt::RecentConfigurationPage::Text),
|
||||
edt::RecentConfigurationPage::ConfigurationDescriptor (cfg_edit_text_size, tl::to_string (tr ("Size")), edt::RecentConfigurationPage::Double),
|
||||
edt::RecentConfigurationPage::ConfigurationDescriptor (cfg_edit_text_halign, tl::to_string (tr ("Hor. align")), edt::RecentConfigurationPage::Text),
|
||||
edt::RecentConfigurationPage::ConfigurationDescriptor (cfg_edit_text_valign, tl::to_string (tr ("Vert. align")), edt::RecentConfigurationPage::Text)
|
||||
};
|
||||
|
||||
ret.push_back (new RecentConfigurationPage (view, dispatcher, "edit-recent-text-param",
|
||||
&text_cfg_descriptors[0], &text_cfg_descriptors[sizeof (text_cfg_descriptors) / sizeof (text_cfg_descriptors[0])]));
|
||||
ret.push_back (new edt::EditorOptionsText (view, dispatcher));
|
||||
}
|
||||
#else
|
||||
static void get_text_editor_options_pages () { }
|
||||
#endif
|
||||
|
||||
static
|
||||
void get_path_options (std::vector < std::pair<std::string, std::string> > &options)
|
||||
{
|
||||
|
|
@ -111,27 +67,6 @@ void get_path_options (std::vector < std::pair<std::string, std::string> > &opti
|
|||
options.push_back (std::pair<std::string, std::string> (cfg_edit_path_ext_var_end, "0.0"));
|
||||
}
|
||||
|
||||
#if defined(HAVE_QT)
|
||||
static
|
||||
void get_path_editor_options_pages (std::vector<lay::EditorOptionsPage *> &ret, lay::LayoutViewBase *view, lay::Dispatcher *dispatcher)
|
||||
{
|
||||
static edt::RecentConfigurationPage::ConfigurationDescriptor path_cfg_descriptors[] =
|
||||
{
|
||||
edt::RecentConfigurationPage::ConfigurationDescriptor ("", tl::to_string (tr ("Layer")), edt::RecentConfigurationPage::Layer),
|
||||
edt::RecentConfigurationPage::ConfigurationDescriptor (cfg_edit_path_width, tl::to_string (tr ("Width")), edt::RecentConfigurationPage::Double),
|
||||
edt::RecentConfigurationPage::ConfigurationDescriptor (cfg_edit_path_ext_type, tl::to_string (tr ("Ends")), edt::RecentConfigurationPage::Int),
|
||||
edt::RecentConfigurationPage::ConfigurationDescriptor (cfg_edit_path_ext_var_begin, tl::to_string (tr ("Begin ext.")), edt::RecentConfigurationPage::Double),
|
||||
edt::RecentConfigurationPage::ConfigurationDescriptor (cfg_edit_path_ext_var_end, tl::to_string (tr ("End ext.")), edt::RecentConfigurationPage::Double)
|
||||
};
|
||||
|
||||
ret.push_back (new RecentConfigurationPage (view, dispatcher, "edit-recent-path-param",
|
||||
&path_cfg_descriptors[0], &path_cfg_descriptors[sizeof (path_cfg_descriptors) / sizeof (path_cfg_descriptors[0])]));
|
||||
ret.push_back (new EditorOptionsPath (view, dispatcher));
|
||||
}
|
||||
#else
|
||||
static void get_path_editor_options_pages () { }
|
||||
#endif
|
||||
|
||||
static
|
||||
void get_inst_options (std::vector < std::pair<std::string, std::string> > &options)
|
||||
{
|
||||
|
|
@ -153,58 +88,17 @@ void get_inst_options (std::vector < std::pair<std::string, std::string> > &opti
|
|||
options.push_back (std::pair<std::string, std::string> (cfg_edit_show_shapes_of_instances, "true"));
|
||||
}
|
||||
|
||||
#if defined(HAVE_QT)
|
||||
static
|
||||
void get_inst_editor_options_pages (std::vector<lay::EditorOptionsPage *> &ret, lay::LayoutViewBase *view, lay::Dispatcher *dispatcher)
|
||||
{
|
||||
static edt::RecentConfigurationPage::ConfigurationDescriptor inst_cfg_descriptors[] =
|
||||
{
|
||||
edt::RecentConfigurationPage::ConfigurationDescriptor (cfg_edit_inst_lib_name, tl::to_string (tr ("Library")), edt::RecentConfigurationPage::CellLibraryName),
|
||||
edt::RecentConfigurationPage::ConfigurationDescriptor (cfg_edit_inst_cell_name, tl::to_string (tr ("Cell")), edt::RecentConfigurationPage::CellDisplayName),
|
||||
edt::RecentConfigurationPage::ConfigurationDescriptor (cfg_edit_inst_angle, tl::to_string (tr ("Angle")), edt::RecentConfigurationPage::Double),
|
||||
edt::RecentConfigurationPage::ConfigurationDescriptor (cfg_edit_inst_mirror, tl::to_string (tr ("Mirror")), edt::RecentConfigurationPage::Bool),
|
||||
edt::RecentConfigurationPage::ConfigurationDescriptor (cfg_edit_inst_scale, tl::to_string (tr ("Scale")), edt::RecentConfigurationPage::Double),
|
||||
edt::RecentConfigurationPage::ConfigurationDescriptor (cfg_edit_inst_array, tl::to_string (tr ("Array")), edt::RecentConfigurationPage::ArrayFlag),
|
||||
edt::RecentConfigurationPage::ConfigurationDescriptor (cfg_edit_inst_rows, tl::to_string (tr ("Rows")), edt::RecentConfigurationPage::IntIfArray),
|
||||
edt::RecentConfigurationPage::ConfigurationDescriptor (cfg_edit_inst_row_x, tl::to_string (tr ("Row step (x)")), edt::RecentConfigurationPage::DoubleIfArray),
|
||||
edt::RecentConfigurationPage::ConfigurationDescriptor (cfg_edit_inst_row_y, tl::to_string (tr ("Row step (y)")), edt::RecentConfigurationPage::DoubleIfArray),
|
||||
edt::RecentConfigurationPage::ConfigurationDescriptor (cfg_edit_inst_columns, tl::to_string (tr ("Columns")), edt::RecentConfigurationPage::IntIfArray),
|
||||
edt::RecentConfigurationPage::ConfigurationDescriptor (cfg_edit_inst_column_x, tl::to_string (tr ("Column step (x)")), edt::RecentConfigurationPage::DoubleIfArray),
|
||||
edt::RecentConfigurationPage::ConfigurationDescriptor (cfg_edit_inst_column_y, tl::to_string (tr ("Column step (y)")), edt::RecentConfigurationPage::DoubleIfArray),
|
||||
edt::RecentConfigurationPage::ConfigurationDescriptor (cfg_edit_inst_pcell_parameters, tl::to_string (tr ("PCell parameters")), edt::RecentConfigurationPage::PCellParameters)
|
||||
};
|
||||
|
||||
ret.push_back (new RecentConfigurationPage (view, dispatcher, "edit-recent-inst-param",
|
||||
&inst_cfg_descriptors[0], &inst_cfg_descriptors[sizeof (inst_cfg_descriptors) / sizeof (inst_cfg_descriptors[0])]));
|
||||
ret.push_back (new EditorOptionsInstPCellParam (view, dispatcher));
|
||||
ret.push_back (new EditorOptionsInst (view, dispatcher));
|
||||
}
|
||||
#else
|
||||
static void get_inst_editor_options_pages () { }
|
||||
#endif
|
||||
|
||||
template <class Svc>
|
||||
class PluginDeclaration
|
||||
: public PluginDeclarationBase
|
||||
{
|
||||
public:
|
||||
#if defined(HAVE_QT)
|
||||
PluginDeclaration (const std::string &title, const std::string &mouse_mode,
|
||||
void (*option_get_f) (std::vector < std::pair<std::string, std::string> > &) = 0,
|
||||
void (*pages_f) (std::vector <lay::EditorOptionsPage *> &, lay::LayoutViewBase *, lay::Dispatcher *) = 0)
|
||||
: m_title (title), m_mouse_mode (mouse_mode), mp_option_get_f (option_get_f), mp_pages_f (pages_f)
|
||||
void (*option_get_f) (std::vector < std::pair<std::string, std::string> > &) = 0)
|
||||
: m_title (title), m_mouse_mode (mouse_mode), mp_option_get_f (option_get_f)
|
||||
{
|
||||
// .. nothing yet ..
|
||||
}
|
||||
#else
|
||||
PluginDeclaration (const std::string &title, const std::string &mouse_mode,
|
||||
void (*option_get_f) (std::vector < std::pair<std::string, std::string> > &) = 0,
|
||||
void (*pages_f) () = 0)
|
||||
: m_title (title), m_mouse_mode (mouse_mode), mp_option_get_f (option_get_f), mp_pages_f (pages_f)
|
||||
{
|
||||
// .. nothing yet ..
|
||||
}
|
||||
#endif
|
||||
|
||||
virtual void get_options (std::vector < std::pair<std::string, std::string> > &options) const
|
||||
{
|
||||
|
|
@ -225,19 +119,6 @@ public:
|
|||
// .. nothing yet ..
|
||||
}
|
||||
|
||||
#if defined(HAVE_QT)
|
||||
virtual void get_editor_options_pages (std::vector<lay::EditorOptionsPage *> &pages, lay::LayoutViewBase *view, lay::Dispatcher *root) const
|
||||
{
|
||||
if (mp_pages_f != 0) {
|
||||
size_t nstart = pages.size ();
|
||||
(*mp_pages_f) (pages, view, root);
|
||||
while (nstart < pages.size ()) {
|
||||
pages [nstart++]->set_plugin_declaration (this);
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
virtual lay::Plugin *create_plugin (db::Manager *manager, lay::Dispatcher *, lay::LayoutViewBase *view) const
|
||||
{
|
||||
Svc *service = new Svc (manager, view);
|
||||
|
|
@ -261,45 +142,47 @@ public:
|
|||
}
|
||||
}
|
||||
|
||||
virtual std::vector<std::string> additional_editor_options_pages () const
|
||||
{
|
||||
std::vector<std::string> names;
|
||||
names.push_back ("GenericEditorOptions");
|
||||
return names;
|
||||
}
|
||||
|
||||
private:
|
||||
std::string m_title;
|
||||
std::string m_mouse_mode;
|
||||
|
||||
void (*mp_option_get_f) (std::vector < std::pair<std::string, std::string> > &options);
|
||||
#if defined(HAVE_QT)
|
||||
void (*mp_pages_f) (std::vector <lay::EditorOptionsPage *> &, lay::LayoutViewBase *, lay::Dispatcher *);
|
||||
#else
|
||||
void (*mp_pages_f) ();
|
||||
#endif
|
||||
};
|
||||
|
||||
static tl::RegisteredClass<lay::PluginDeclaration> config_decl1 (
|
||||
new edt::PluginDeclaration<edt::PolygonService> (tl::to_string (tr ("Polygons")), "polygon:edit_mode\t" + tl::to_string (tr ("Polygon")) + "<:polygon_24px.png>" + tl::to_string (tr ("{Create a polygon}")), 0, &get_shape_editor_options_pages),
|
||||
new edt::PluginDeclaration<edt::PolygonService> (tl::to_string (tr ("Polygons")), "polygon:edit_mode\t" + tl::to_string (tr ("Polygon")) + "<:polygon_24px.png>" + tl::to_string (tr ("{Create a polygon}")), 0),
|
||||
4010,
|
||||
"edt::Service(Polygons)"
|
||||
);
|
||||
static tl::RegisteredClass<lay::PluginDeclaration> config_decl2 (
|
||||
new edt::PluginDeclaration<edt::BoxService> (tl::to_string (tr ("Boxes")), "box:edit_mode\t" + tl::to_string (tr ("Box")) + "\t<:box_24px.png>" + tl::to_string (tr ("{Create a box}")), 0, &get_shape_editor_options_pages),
|
||||
new edt::PluginDeclaration<edt::BoxService> (tl::to_string (tr ("Boxes")), "box:edit_mode\t" + tl::to_string (tr ("Box")) + "\t<:box_24px.png>" + tl::to_string (tr ("{Create a box}")), 0),
|
||||
4011,
|
||||
"edt::Service(Boxes)"
|
||||
);
|
||||
static tl::RegisteredClass<lay::PluginDeclaration> config_decl3 (
|
||||
new edt::PluginDeclaration<edt::TextService> (tl::to_string (tr ("Texts")), "text:edit_mode\t" + tl::to_string (tr ("Text")) + "\t<:text_24px.png>" + tl::to_string (tr ("{Create a text object}")), &get_text_options, &get_text_editor_options_pages),
|
||||
new edt::PluginDeclaration<edt::TextService> (tl::to_string (tr ("Texts")), "text:edit_mode\t" + tl::to_string (tr ("Text")) + "\t<:text_24px.png>" + tl::to_string (tr ("{Create a text object}")), &get_text_options),
|
||||
4012,
|
||||
"edt::Service(Texts)"
|
||||
);
|
||||
static tl::RegisteredClass<lay::PluginDeclaration> config_decl4 (
|
||||
new edt::PluginDeclaration<edt::PathService> (tl::to_string (tr ("Paths")), "path:edit_mode\t" + tl::to_string (tr ("Path")) + "\t<:path_24px.png>" + tl::to_string (tr ("{Create a path}")), &get_path_options, &get_path_editor_options_pages),
|
||||
new edt::PluginDeclaration<edt::PathService> (tl::to_string (tr ("Paths")), "path:edit_mode\t" + tl::to_string (tr ("Path")) + "\t<:path_24px.png>" + tl::to_string (tr ("{Create a path}")), &get_path_options),
|
||||
4013,
|
||||
"edt::Service(Paths)"
|
||||
);
|
||||
static tl::RegisteredClass<lay::PluginDeclaration> config_decl5 (
|
||||
new edt::PluginDeclaration<edt::PointService> (tl::to_string (tr ("Points")), std::string (), 0, &get_shape_editor_options_pages),
|
||||
new edt::PluginDeclaration<edt::PointService> (tl::to_string (tr ("Points")), std::string (), 0),
|
||||
4014,
|
||||
"edt::Service(Points)"
|
||||
);
|
||||
static tl::RegisteredClass<lay::PluginDeclaration> config_decl6 (
|
||||
new edt::PluginDeclaration<edt::InstService> (tl::to_string (tr ("Instances")), "instance:edit_mode\t" + tl::to_string (tr ("Instance")) + "\t<:instance_24px.png>" + tl::to_string (tr ("{Create a cell instance}")), &get_inst_options, &get_inst_editor_options_pages),
|
||||
new edt::PluginDeclaration<edt::InstService> (tl::to_string (tr ("Instances")), "instance:edit_mode\t" + tl::to_string (tr ("Instance")) + "\t<:instance_24px.png>" + tl::to_string (tr ("{Create a cell instance}")), &get_inst_options),
|
||||
4020,
|
||||
"edt::Service(CellInstances)"
|
||||
);
|
||||
|
|
@ -418,15 +301,6 @@ public:
|
|||
return false;
|
||||
}
|
||||
|
||||
#if defined(HAVE_QT)
|
||||
virtual void get_editor_options_pages (std::vector<lay::EditorOptionsPage *> &pages, lay::LayoutViewBase *view, lay::Dispatcher *dispatcher) const
|
||||
{
|
||||
// NOTE: we do not set plugin_declaration which makes the page unspecific
|
||||
EditorOptionsGeneric *generic_opt = new EditorOptionsGeneric (view, dispatcher);
|
||||
pages.push_back (generic_opt);
|
||||
}
|
||||
#endif
|
||||
|
||||
virtual void initialize (lay::Dispatcher *root)
|
||||
{
|
||||
lay::Dispatcher *mp = lay::Dispatcher::instance ();
|
||||
|
|
@ -524,16 +398,6 @@ public:
|
|||
// .. nothing yet ..
|
||||
}
|
||||
|
||||
virtual void get_options (std::vector < std::pair<std::string, std::string> > & /*options*/) const
|
||||
{
|
||||
// .. nothing yet ..
|
||||
}
|
||||
|
||||
virtual void get_editor_options_pages (std::vector<lay::EditorOptionsPage *> & /*pages*/, lay::LayoutViewBase * /*view*/, lay::Dispatcher * /*root*/) const
|
||||
{
|
||||
// .. no specific ones ..
|
||||
}
|
||||
|
||||
virtual lay::Plugin *create_plugin (db::Manager *manager, lay::Dispatcher *root, lay::LayoutViewBase *view) const
|
||||
{
|
||||
return new edt::PartialService (manager, view, root);
|
||||
|
|
@ -551,6 +415,13 @@ public:
|
|||
return true;
|
||||
}
|
||||
|
||||
virtual std::vector<std::string> additional_editor_options_pages () const
|
||||
{
|
||||
std::vector<std::string> names;
|
||||
names.push_back ("GenericEditorOptions");
|
||||
return names;
|
||||
}
|
||||
|
||||
private:
|
||||
std::string m_title;
|
||||
std::string m_mouse_mode;
|
||||
|
|
|
|||
|
|
@ -124,7 +124,7 @@ PointService::do_mouse_click (const db::DPoint &p)
|
|||
}
|
||||
|
||||
void
|
||||
PointService::do_finish_edit ()
|
||||
PointService::do_finish_edit (bool /*accept*/)
|
||||
{
|
||||
deliver_shape (get_point ());
|
||||
commit_recent ();
|
||||
|
|
|
|||
|
|
@ -45,7 +45,7 @@ public:
|
|||
virtual void do_mouse_move (const db::DPoint &p);
|
||||
virtual void do_mouse_move_inactive (const db::DPoint &p);
|
||||
virtual bool do_mouse_click (const db::DPoint &p);
|
||||
virtual void do_finish_edit ();
|
||||
virtual void do_finish_edit (bool);
|
||||
virtual void do_cancel_edit ();
|
||||
virtual bool selection_applies (const lay::ObjectInstPath &sel) const;
|
||||
|
||||
|
|
|
|||
|
|
@ -24,6 +24,7 @@
|
|||
#include "edtPolygonService.h"
|
||||
|
||||
#include "layLayoutViewBase.h"
|
||||
#include "layEditorOptionsPage.h"
|
||||
|
||||
#if defined(HAVE_QT)
|
||||
# include "edtPropertiesPages.h"
|
||||
|
|
@ -135,13 +136,44 @@ PolygonService::do_mouse_click (const db::DPoint &p)
|
|||
}
|
||||
|
||||
void
|
||||
PolygonService::do_finish_edit ()
|
||||
PolygonService::do_finish_edit (bool accept)
|
||||
{
|
||||
if (accept) {
|
||||
// add a dummy point in this case for the current one
|
||||
m_last = m_points.back ();
|
||||
m_points.push_back (db::DPoint ());
|
||||
}
|
||||
|
||||
deliver_shape (get_polygon (false));
|
||||
commit_recent ();
|
||||
close_editor_hooks (true);
|
||||
}
|
||||
|
||||
void
|
||||
PolygonService::function (const std::string &name, const std::string &value)
|
||||
{
|
||||
if (name == ShapeEditService::connection_function_name ()) {
|
||||
|
||||
try {
|
||||
|
||||
db::DVector dim;
|
||||
tl::from_string (value, dim);
|
||||
|
||||
if (m_points.size () >= 2) {
|
||||
|
||||
m_last = m_points.back () = m_points.end () [-2] + dim;
|
||||
m_points.push_back (m_last);
|
||||
|
||||
update_marker ();
|
||||
|
||||
}
|
||||
|
||||
} catch (...) {
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
db::Polygon
|
||||
PolygonService::get_polygon (bool editing) const
|
||||
{
|
||||
|
|
@ -363,12 +395,17 @@ PolygonService::update_marker ()
|
|||
}
|
||||
|
||||
if (m_points.size () >= 2) {
|
||||
db::DVector dim = m_points.back () - m_points [m_points.size () - 2];
|
||||
view ()->message (std::string ("lx: ") +
|
||||
tl::micron_to_string (m_points.back ().x () - m_points.end () [-2].x ()) +
|
||||
tl::micron_to_string (dim.x ()) +
|
||||
std::string (" ly: ") +
|
||||
tl::micron_to_string (m_points.back ().y () - m_points.end () [-2].y ()) +
|
||||
tl::micron_to_string (dim.y ()) +
|
||||
std::string (" l: ") +
|
||||
tl::micron_to_string (m_points.back ().distance (m_points.end () [-2])));
|
||||
tl::micron_to_string (dim.length ()));
|
||||
auto tb = toolbox_widget ();
|
||||
if (tb) {
|
||||
tb->configure (ShapeEditService::connection_configure_name (), dim.to_string ());
|
||||
}
|
||||
}
|
||||
|
||||
// call hooks with new shape
|
||||
|
|
|
|||
|
|
@ -46,9 +46,10 @@ public:
|
|||
virtual void do_mouse_move (const db::DPoint &p);
|
||||
virtual void do_mouse_move_inactive (const db::DPoint &p);
|
||||
virtual bool do_mouse_click (const db::DPoint &p);
|
||||
virtual void do_finish_edit ();
|
||||
virtual void do_finish_edit (bool);
|
||||
virtual void do_cancel_edit ();
|
||||
virtual bool selection_applies (const lay::ObjectInstPath &sel) const;
|
||||
virtual void function (const std::string &name, const std::string &value);
|
||||
|
||||
private:
|
||||
std::vector <db::DPoint> m_points;
|
||||
|
|
|
|||
|
|
@ -23,6 +23,7 @@
|
|||
#if defined(HAVE_QT)
|
||||
|
||||
#include "edtRecentConfigurationPage.h"
|
||||
#include "edtConfig.h"
|
||||
#include "layDispatcher.h"
|
||||
#include "layLayoutViewBase.h"
|
||||
#include "layLayerTreeModel.h"
|
||||
|
|
@ -497,6 +498,92 @@ RecentConfigurationPage::config_recent_for_layer (lay::Dispatcher *root, const d
|
|||
}
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------
|
||||
// Configurations and registrations
|
||||
|
||||
namespace {
|
||||
|
||||
class RecentShapeConfigurationPage
|
||||
: public edt::RecentConfigurationPage
|
||||
{
|
||||
public:
|
||||
RecentShapeConfigurationPage (lay::LayoutViewBase *view, lay::Dispatcher *dispatcher)
|
||||
: edt::RecentConfigurationPage (view, dispatcher, "edit-recent-shape-param")
|
||||
{
|
||||
add (edt::RecentConfigurationPage::ConfigurationDescriptor ("", tl::to_string (tr ("Layer")), edt::RecentConfigurationPage::Layer));
|
||||
|
||||
init ();
|
||||
}
|
||||
};
|
||||
|
||||
class RecentTextConfigurationPage
|
||||
: public edt::RecentConfigurationPage
|
||||
{
|
||||
public:
|
||||
RecentTextConfigurationPage (lay::LayoutViewBase *view, lay::Dispatcher *dispatcher)
|
||||
: edt::RecentConfigurationPage (view, dispatcher, "edit-recent-text-param")
|
||||
{
|
||||
add (edt::RecentConfigurationPage::ConfigurationDescriptor ("", tl::to_string (tr ("Layer")), edt::RecentConfigurationPage::Layer));
|
||||
add (edt::RecentConfigurationPage::ConfigurationDescriptor (cfg_edit_text_string, tl::to_string (tr ("Text")), edt::RecentConfigurationPage::Text));
|
||||
add (edt::RecentConfigurationPage::ConfigurationDescriptor (cfg_edit_text_size, tl::to_string (tr ("Size")), edt::RecentConfigurationPage::Double));
|
||||
add (edt::RecentConfigurationPage::ConfigurationDescriptor (cfg_edit_text_halign, tl::to_string (tr ("Hor. align")), edt::RecentConfigurationPage::Text));
|
||||
add (edt::RecentConfigurationPage::ConfigurationDescriptor (cfg_edit_text_valign, tl::to_string (tr ("Vert. align")), edt::RecentConfigurationPage::Text));
|
||||
|
||||
init ();
|
||||
}
|
||||
};
|
||||
|
||||
class RecentPathConfigurationPage
|
||||
: public edt::RecentConfigurationPage
|
||||
{
|
||||
public:
|
||||
RecentPathConfigurationPage (lay::LayoutViewBase *view, lay::Dispatcher *dispatcher)
|
||||
: edt::RecentConfigurationPage (view, dispatcher, "edit-recent-path-param")
|
||||
{
|
||||
add (edt::RecentConfigurationPage::ConfigurationDescriptor ("", tl::to_string (tr ("Layer")), edt::RecentConfigurationPage::Layer));
|
||||
add (edt::RecentConfigurationPage::ConfigurationDescriptor (cfg_edit_path_width, tl::to_string (tr ("Width")), edt::RecentConfigurationPage::Double));
|
||||
add (edt::RecentConfigurationPage::ConfigurationDescriptor (cfg_edit_path_ext_type, tl::to_string (tr ("Ends")), edt::RecentConfigurationPage::Int));
|
||||
add (edt::RecentConfigurationPage::ConfigurationDescriptor (cfg_edit_path_ext_var_begin, tl::to_string (tr ("Begin ext.")), edt::RecentConfigurationPage::Double));
|
||||
add (edt::RecentConfigurationPage::ConfigurationDescriptor (cfg_edit_path_ext_var_end, tl::to_string (tr ("End ext.")), edt::RecentConfigurationPage::Double));
|
||||
|
||||
init ();
|
||||
}
|
||||
};
|
||||
|
||||
class RecentInstConfigurationPage
|
||||
: public edt::RecentConfigurationPage
|
||||
{
|
||||
public:
|
||||
RecentInstConfigurationPage (lay::LayoutViewBase *view, lay::Dispatcher *dispatcher)
|
||||
: edt::RecentConfigurationPage (view, dispatcher, "edit-recent-inst-param")
|
||||
{
|
||||
add (edt::RecentConfigurationPage::ConfigurationDescriptor (cfg_edit_inst_lib_name, tl::to_string (tr ("Library")), edt::RecentConfigurationPage::CellLibraryName));
|
||||
add (edt::RecentConfigurationPage::ConfigurationDescriptor (cfg_edit_inst_cell_name, tl::to_string (tr ("Cell")), edt::RecentConfigurationPage::CellDisplayName));
|
||||
add (edt::RecentConfigurationPage::ConfigurationDescriptor (cfg_edit_inst_angle, tl::to_string (tr ("Angle")), edt::RecentConfigurationPage::Double));
|
||||
add (edt::RecentConfigurationPage::ConfigurationDescriptor (cfg_edit_inst_mirror, tl::to_string (tr ("Mirror")), edt::RecentConfigurationPage::Bool));
|
||||
add (edt::RecentConfigurationPage::ConfigurationDescriptor (cfg_edit_inst_scale, tl::to_string (tr ("Scale")), edt::RecentConfigurationPage::Double));
|
||||
add (edt::RecentConfigurationPage::ConfigurationDescriptor (cfg_edit_inst_array, tl::to_string (tr ("Array")), edt::RecentConfigurationPage::ArrayFlag));
|
||||
add (edt::RecentConfigurationPage::ConfigurationDescriptor (cfg_edit_inst_rows, tl::to_string (tr ("Rows")), edt::RecentConfigurationPage::IntIfArray));
|
||||
add (edt::RecentConfigurationPage::ConfigurationDescriptor (cfg_edit_inst_row_x, tl::to_string (tr ("Row step (x)")), edt::RecentConfigurationPage::DoubleIfArray));
|
||||
add (edt::RecentConfigurationPage::ConfigurationDescriptor (cfg_edit_inst_row_y, tl::to_string (tr ("Row step (y)")), edt::RecentConfigurationPage::DoubleIfArray));
|
||||
add (edt::RecentConfigurationPage::ConfigurationDescriptor (cfg_edit_inst_columns, tl::to_string (tr ("Columns")), edt::RecentConfigurationPage::IntIfArray));
|
||||
add (edt::RecentConfigurationPage::ConfigurationDescriptor (cfg_edit_inst_column_x, tl::to_string (tr ("Column step (x)")), edt::RecentConfigurationPage::DoubleIfArray));
|
||||
add (edt::RecentConfigurationPage::ConfigurationDescriptor (cfg_edit_inst_column_y, tl::to_string (tr ("Column step (y)")), edt::RecentConfigurationPage::DoubleIfArray));
|
||||
add (edt::RecentConfigurationPage::ConfigurationDescriptor (cfg_edit_inst_pcell_parameters, tl::to_string (tr ("PCell parameters")), edt::RecentConfigurationPage::PCellParameters));
|
||||
|
||||
init ();
|
||||
}
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
static tl::RegisteredClass<lay::EditorOptionsPageFactoryBase> s_factory_polygons (new lay::EditorOptionsPageFactory<RecentShapeConfigurationPage> ("edt::Service(Polygons)"), 0);
|
||||
static tl::RegisteredClass<lay::EditorOptionsPageFactoryBase> s_factory_boxes (new lay::EditorOptionsPageFactory<RecentShapeConfigurationPage> ("edt::Service(Boxes)"), 0);
|
||||
static tl::RegisteredClass<lay::EditorOptionsPageFactoryBase> s_factory_points (new lay::EditorOptionsPageFactory<RecentShapeConfigurationPage> ("edt::Service(Points)"), 0);
|
||||
static tl::RegisteredClass<lay::EditorOptionsPageFactoryBase> s_factory_texts (new lay::EditorOptionsPageFactory<RecentTextConfigurationPage> ("edt::Service(Texts)"), 0);
|
||||
static tl::RegisteredClass<lay::EditorOptionsPageFactoryBase> s_factory_paths (new lay::EditorOptionsPageFactory<RecentPathConfigurationPage> ("edt::Service(Paths)"), 0);
|
||||
static tl::RegisteredClass<lay::EditorOptionsPageFactoryBase> s_factory_insts (new lay::EditorOptionsPageFactory<RecentInstConfigurationPage> ("edt::Service(CellInstances)"), 0);
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
|
|
|
|||
|
|
@ -26,7 +26,7 @@
|
|||
#define HDR_edtRecentConfigurationPage
|
||||
|
||||
#include "edtCommon.h"
|
||||
#include "layEditorOptionsPage.h"
|
||||
#include "layEditorOptionsPageWidget.h"
|
||||
#include "tlObject.h"
|
||||
#include "tlDeferredExecution.h"
|
||||
|
||||
|
|
@ -48,13 +48,11 @@ namespace edt
|
|||
|
||||
class PCellParametersPage;
|
||||
|
||||
class EditorOptionsPages;
|
||||
|
||||
/**
|
||||
* @brief The base class for a object properties page
|
||||
*/
|
||||
class EDT_PUBLIC RecentConfigurationPage
|
||||
: public lay::EditorOptionsPage
|
||||
: public lay::EditorOptionsPageWidget
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
|
|
@ -84,11 +82,10 @@ public:
|
|||
ConfigurationRendering rendering;
|
||||
};
|
||||
|
||||
template <class Iter>
|
||||
RecentConfigurationPage (lay::LayoutViewBase *view, lay::Dispatcher *dispatcher, const std::string &recent_cfg_name, Iter begin_cfg, Iter end_cfg)
|
||||
: EditorOptionsPage (view, dispatcher), m_recent_cfg_name (recent_cfg_name), m_cfg (begin_cfg, end_cfg), dm_update_list (this, &RecentConfigurationPage::update_list)
|
||||
RecentConfigurationPage (lay::LayoutViewBase *view, lay::Dispatcher *dispatcher, const std::string &recent_cfg_name)
|
||||
: EditorOptionsPageWidget (view, dispatcher), m_recent_cfg_name (recent_cfg_name), dm_update_list (this, &RecentConfigurationPage::update_list)
|
||||
{
|
||||
init ();
|
||||
// .. nothing yet ..
|
||||
}
|
||||
|
||||
virtual ~RecentConfigurationPage ();
|
||||
|
|
@ -100,6 +97,21 @@ public:
|
|||
virtual void commit_recent (lay::Dispatcher *root);
|
||||
virtual void config_recent_for_layer (lay::Dispatcher *root, const db::LayerProperties &lp, int cv_index);
|
||||
|
||||
protected:
|
||||
/**
|
||||
* @brief Adds a configuration descriptors
|
||||
* Use this method in the constructor to add descriptors.
|
||||
*/
|
||||
void add (const ConfigurationDescriptor &cfg)
|
||||
{
|
||||
m_cfg.push_back (cfg);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Initializes the widget after the configuration items have been added
|
||||
*/
|
||||
void init ();
|
||||
|
||||
private slots:
|
||||
void item_clicked (QTreeWidgetItem *item);
|
||||
|
||||
|
|
@ -109,7 +121,6 @@ private:
|
|||
QTreeWidget *mp_tree_widget;
|
||||
tl::DeferredMethod<RecentConfigurationPage> dm_update_list;
|
||||
|
||||
void init ();
|
||||
void update_list (const std::list<std::vector<std::string> > &stored_values);
|
||||
void update_list ();
|
||||
std::list<std::vector<std::string> > get_stored_values () const;
|
||||
|
|
|
|||
|
|
@ -32,7 +32,7 @@
|
|||
#include "layLayoutView.h"
|
||||
#include "laySnap.h"
|
||||
#include "layConverters.h"
|
||||
#include "layEditorOptionsPages.h"
|
||||
#include "layEditorOptionsPage.h"
|
||||
#include "tlProgress.h"
|
||||
#include "tlTimer.h"
|
||||
|
||||
|
|
@ -46,7 +46,7 @@ Service::Service (db::Manager *manager, lay::LayoutViewBase *view, db::ShapeIter
|
|||
db::Object (manager),
|
||||
mp_view (view),
|
||||
mp_transient_marker (0),
|
||||
m_mouse_in_view (false), m_editing (false), m_immediate (false),
|
||||
m_mouse_buttons (0), m_mouse_in_view (false), m_editing (false), m_immediate (false),
|
||||
m_selection_maybe_invalid (false),
|
||||
m_cell_inst_service (false),
|
||||
m_flags (flags),
|
||||
|
|
@ -70,7 +70,7 @@ Service::Service (db::Manager *manager, lay::LayoutViewBase *view)
|
|||
db::Object (manager),
|
||||
mp_view (view),
|
||||
mp_transient_marker (0),
|
||||
m_mouse_in_view (false), m_editing (false), m_immediate (false),
|
||||
m_mouse_buttons (0), m_mouse_in_view (false), m_editing (false), m_immediate (false),
|
||||
m_selection_maybe_invalid (false),
|
||||
m_cell_inst_service (true),
|
||||
m_flags (db::ShapeIterator::Nothing),
|
||||
|
|
@ -103,14 +103,21 @@ Service::~Service ()
|
|||
clear_transient_selection ();
|
||||
}
|
||||
|
||||
lay::angle_constraint_type
|
||||
lay::angle_constraint_type
|
||||
Service::alt_ac () const
|
||||
{
|
||||
// fetch m_alt_ac (which is set from mouse buttons)
|
||||
return m_alt_ac;
|
||||
}
|
||||
|
||||
lay::angle_constraint_type
|
||||
Service::connect_ac () const
|
||||
{
|
||||
// m_alt_ac (which is set from mouse buttons) can override the specified connect angle constraint
|
||||
return m_alt_ac != lay::AC_Global ? m_alt_ac : m_connect_ac;
|
||||
}
|
||||
|
||||
lay::angle_constraint_type
|
||||
lay::angle_constraint_type
|
||||
Service::move_ac () const
|
||||
{
|
||||
// m_alt_ac (which is set from mouse buttons) can override the specified move angle constraint
|
||||
|
|
@ -290,11 +297,23 @@ Service::snap2 (const db::DPoint &p) const
|
|||
return snap2_details (p).snapped_point;
|
||||
}
|
||||
|
||||
lay::PointSnapToObjectResult
|
||||
Service::snap2_details (const db::DPoint &p, const db::DPoint &plast, lay::angle_constraint_type ac) const
|
||||
{
|
||||
double snap_range = ui ()->mouse_event_trans ().inverted ().ctrans (lay::snap_range_pixels ());
|
||||
return lay::obj_snap (m_snap_to_objects ? view () : 0, plast, p, m_edit_grid == db::DVector () ? m_global_grid : m_edit_grid, ac, snap_range);
|
||||
}
|
||||
|
||||
lay::PointSnapToObjectResult
|
||||
Service::snap2_details (const db::DPoint &p, const db::DPoint &plast, bool connect) const
|
||||
{
|
||||
return snap2_details (p, plast, connect ? connect_ac () : move_ac ());
|
||||
}
|
||||
|
||||
db::DPoint
|
||||
Service::snap2 (const db::DPoint &p, const db::DPoint &plast, bool connect) const
|
||||
{
|
||||
double snap_range = ui ()->mouse_event_trans ().inverted ().ctrans (lay::snap_range_pixels ());
|
||||
return lay::obj_snap (m_snap_to_objects ? view () : 0, plast, p, m_edit_grid == db::DVector () ? m_global_grid : m_edit_grid, connect ? connect_ac () : move_ac (), snap_range).snapped_point;
|
||||
return snap2_details (p, plast, connect ? connect_ac () : move_ac ()).snapped_point;
|
||||
}
|
||||
|
||||
void
|
||||
|
|
@ -544,15 +563,20 @@ void
|
|||
Service::move (const db::DPoint &pu, lay::angle_constraint_type ac)
|
||||
{
|
||||
m_alt_ac = ac;
|
||||
|
||||
if (view ()->is_editable () && m_moving) {
|
||||
|
||||
db::DPoint ref = snap (m_move_start);
|
||||
bool snapped = false;
|
||||
db::DPoint p = ref + snap_marker_to_grid (pu - m_move_start, snapped);
|
||||
if (! snapped) {
|
||||
p = ref + snap (pu - m_move_start, false /*move*/);
|
||||
}
|
||||
|
||||
move_markers (db::DTrans (p - db::DPoint ()) * db::DTrans (m_move_trans.fp_trans ()) * db::DTrans (db::DPoint () - ref));
|
||||
|
||||
}
|
||||
|
||||
m_alt_ac = lay::AC_Global;
|
||||
}
|
||||
|
||||
|
|
@ -560,28 +584,46 @@ void
|
|||
Service::move_transform (const db::DPoint &pu, db::DFTrans tr, lay::angle_constraint_type ac)
|
||||
{
|
||||
m_alt_ac = ac;
|
||||
|
||||
if (view ()->is_editable () && m_moving) {
|
||||
|
||||
db::DPoint ref = snap (m_move_start);
|
||||
bool snapped = false;
|
||||
db::DPoint p = ref + snap_marker_to_grid (pu - m_move_start, snapped);
|
||||
if (! snapped) {
|
||||
p = ref + snap (pu - m_move_start, false /*move*/);
|
||||
}
|
||||
|
||||
move_markers (db::DTrans (p - db::DPoint ()) * db::DTrans (tr * m_move_trans.fp_trans ()) * db::DTrans (db::DPoint () - ref));
|
||||
|
||||
}
|
||||
|
||||
m_alt_ac = lay::AC_Global;
|
||||
}
|
||||
|
||||
void
|
||||
Service::end_move (const db::DPoint & /*p*/, lay::angle_constraint_type ac)
|
||||
void
|
||||
Service::end_move (const db::DVector &v)
|
||||
{
|
||||
if (view ()->is_editable () && m_moving) {
|
||||
transform (db::DCplxTrans (db::DTrans (v) * db::DTrans (m_move_trans.fp_trans ())));
|
||||
move_cancel (); // formally this functionality fits here
|
||||
// accept changes to guiding shapes
|
||||
handle_guiding_shape_changes (true);
|
||||
}
|
||||
|
||||
m_alt_ac = lay::AC_Global;
|
||||
}
|
||||
|
||||
void
|
||||
Service::end_move (const db::DPoint & /*p*/, lay::angle_constraint_type /*ac*/)
|
||||
{
|
||||
m_alt_ac = ac;
|
||||
if (view ()->is_editable () && m_moving) {
|
||||
transform (db::DCplxTrans (m_move_trans));
|
||||
move_cancel (); // formally this functionality fits here
|
||||
// accept changes to guiding shapes
|
||||
handle_guiding_shape_changes (true);
|
||||
}
|
||||
|
||||
m_alt_ac = lay::AC_Global;
|
||||
}
|
||||
|
||||
|
|
@ -860,6 +902,7 @@ bool
|
|||
Service::mouse_move_event (const db::DPoint &p, unsigned int buttons, bool prio)
|
||||
{
|
||||
m_mouse_pos = p;
|
||||
m_mouse_buttons = buttons;
|
||||
|
||||
if (view ()->is_editable () && prio) {
|
||||
|
||||
|
|
@ -896,6 +939,9 @@ Service::mouse_move_event (const db::DPoint &p, unsigned int buttons, bool prio)
|
|||
bool
|
||||
Service::mouse_press_event (const db::DPoint &p, unsigned int buttons, bool prio)
|
||||
{
|
||||
m_mouse_pos = p;
|
||||
m_mouse_buttons = buttons;
|
||||
|
||||
if (view ()->is_editable () && prio) {
|
||||
|
||||
if ((buttons & lay::LeftButton) != 0) {
|
||||
|
|
@ -910,9 +956,7 @@ Service::mouse_press_event (const db::DPoint &p, unsigned int buttons, bool prio
|
|||
|
||||
} else {
|
||||
if (do_mouse_click (p)) {
|
||||
m_editing = false;
|
||||
set_edit_marker (0);
|
||||
do_finish_edit ();
|
||||
finish_editing (false);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -942,14 +986,14 @@ Service::enter_event (bool /*prio*/)
|
|||
}
|
||||
|
||||
bool
|
||||
Service::mouse_double_click_event (const db::DPoint & /*p*/, unsigned int buttons, bool prio)
|
||||
Service::mouse_double_click_event (const db::DPoint &p, unsigned int buttons, bool prio)
|
||||
{
|
||||
m_mouse_pos = p;
|
||||
m_mouse_buttons = buttons;
|
||||
|
||||
if (m_editing && prio && (buttons & lay::LeftButton) != 0) {
|
||||
m_alt_ac = lay::ac_from_buttons (buttons);
|
||||
do_finish_edit ();
|
||||
m_editing = false;
|
||||
set_edit_marker (0);
|
||||
m_alt_ac = lay::AC_Global;
|
||||
finish_editing (false);
|
||||
return true;
|
||||
} else {
|
||||
return false;
|
||||
|
|
@ -959,6 +1003,9 @@ Service::mouse_double_click_event (const db::DPoint & /*p*/, unsigned int button
|
|||
bool
|
||||
Service::mouse_click_event (const db::DPoint &p, unsigned int buttons, bool prio)
|
||||
{
|
||||
m_mouse_pos = p;
|
||||
m_mouse_buttons = buttons;
|
||||
|
||||
if (view ()->is_editable () && prio && (buttons & lay::RightButton) != 0 && m_editing) {
|
||||
m_alt_ac = lay::ac_from_buttons (buttons);
|
||||
do_mouse_transform (p, db::DFTrans (db::DFTrans::r90));
|
||||
|
|
@ -975,11 +1022,26 @@ Service::key_event (unsigned int key, unsigned int buttons)
|
|||
if (view ()->is_editable () && m_editing && buttons == 0 && key == lay::KeyBackspace) {
|
||||
do_delete ();
|
||||
return true;
|
||||
} else if (view ()->is_editable () && m_editing && buttons == 0 && (key == lay::KeyEnter || key == lay::KeyReturn)) {
|
||||
m_alt_ac = lay::AC_Global;
|
||||
finish_editing (true);
|
||||
return true;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
Service::finish_editing (bool accept)
|
||||
{
|
||||
do_finish_edit (accept);
|
||||
|
||||
m_editing = false;
|
||||
show_toolbox (false);
|
||||
set_edit_marker (0);
|
||||
m_alt_ac = lay::AC_Global;
|
||||
}
|
||||
|
||||
void
|
||||
Service::activated ()
|
||||
{
|
||||
|
|
@ -1682,16 +1744,11 @@ Service::select (const lay::ObjectInstPath &obj, lay::Editable::SelectionMode mo
|
|||
void
|
||||
Service::move_markers (const db::DTrans &t)
|
||||
{
|
||||
if (m_move_trans != t) {
|
||||
if (has_selection ()) {
|
||||
propose_move_transformation (t, 0);
|
||||
}
|
||||
|
||||
// display current move vector
|
||||
if (has_selection ()) {
|
||||
std::string pos = std::string ("dx: ") + tl::micron_to_string (t.disp ().x ()) + " dy: " + tl::micron_to_string (t.disp ().y ());
|
||||
if (t.rot () != 0) {
|
||||
pos += std::string (" ") + ((const db::DFTrans &) t).to_string ();
|
||||
}
|
||||
view ()->message (pos);
|
||||
}
|
||||
if (m_move_trans != t) {
|
||||
|
||||
for (auto r = m_markers.begin (); r != m_markers.end (); ++r) {
|
||||
|
||||
|
|
@ -1712,6 +1769,7 @@ void
|
|||
Service::begin_edit (const db::DPoint &p)
|
||||
{
|
||||
do_begin_edit (p);
|
||||
show_toolbox (true);
|
||||
m_editing = true;
|
||||
}
|
||||
|
||||
|
|
@ -2005,18 +2063,44 @@ Service::handle_guiding_shape_changes (bool commit)
|
|||
void
|
||||
Service::commit_recent ()
|
||||
{
|
||||
#if defined(HAVE_QT)
|
||||
lay::EditorOptionsPages *eo_pages = view ()->editor_options_pages ();
|
||||
if (!eo_pages) {
|
||||
lay::EditorOptionsPageCollection *eo_pages = view ()->editor_options_pages ();
|
||||
if (! eo_pages) {
|
||||
return;
|
||||
}
|
||||
|
||||
for (std::vector<lay::EditorOptionsPage *>::const_iterator op = eo_pages->pages ().begin (); op != eo_pages->pages ().end (); ++op) {
|
||||
if ((*op)->plugin_declaration () == plugin_declaration ()) {
|
||||
auto pages = eo_pages->editor_options_pages ();
|
||||
for (auto op = pages.begin (); op != pages.end (); ++op) {
|
||||
if ((*op)->for_plugin_declaration (plugin_declaration ())) {
|
||||
(*op)->commit_recent (view ());
|
||||
}
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
void
|
||||
Service::show_toolbox (bool visible)
|
||||
{
|
||||
auto p = toolbox_widget ();
|
||||
if (p) {
|
||||
p->set_visible (visible);
|
||||
}
|
||||
}
|
||||
|
||||
lay::EditorOptionsPage *
|
||||
Service::toolbox_widget ()
|
||||
{
|
||||
lay::EditorOptionsPageCollection *eo_pages = view ()->editor_options_pages ();
|
||||
if (! eo_pages) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
auto pages = eo_pages->editor_options_pages (plugin_declaration ());
|
||||
for (auto op = pages.begin (); op != pages.end (); ++op) {
|
||||
if ((*op)->is_toolbox_widget ()) {
|
||||
return *op;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
// -------------------------------------------------------------
|
||||
|
|
|
|||
|
|
@ -190,6 +190,11 @@ public:
|
|||
*/
|
||||
virtual void end_move (const db::DPoint &p, lay::angle_constraint_type ac);
|
||||
|
||||
/**
|
||||
* @brief Terminate a "move" operation with compulsory move vector
|
||||
*/
|
||||
virtual void end_move (const db::DVector &v);
|
||||
|
||||
/**
|
||||
* @brief Indicates whether objects are selected
|
||||
*/
|
||||
|
|
@ -513,9 +518,12 @@ protected:
|
|||
/**
|
||||
* @brief Reimplemented by the specific implementation of the shape editors
|
||||
*
|
||||
* This method is called when the object is finished
|
||||
* This method is called when the object is finished.
|
||||
*
|
||||
* 'accept' is set to true if triggered by the Enter/Return key, false if triggered by a mouse click.
|
||||
* In the latter case, first the mouse click is delivered and then "do_finish_edit" is called.
|
||||
*/
|
||||
virtual void do_finish_edit () { }
|
||||
virtual void do_finish_edit (bool /*accept*/) { }
|
||||
|
||||
/**
|
||||
* @brief Reimplemented by the specific implementation of the shape editors
|
||||
|
|
@ -611,6 +619,7 @@ protected:
|
|||
db::DPoint snap2 (const db::DPoint &p, const db::DPoint &plast, bool connect = true) const;
|
||||
|
||||
protected:
|
||||
lay::angle_constraint_type alt_ac () const;
|
||||
lay::angle_constraint_type connect_ac () const;
|
||||
lay::angle_constraint_type move_ac () const;
|
||||
|
||||
|
|
@ -644,16 +653,49 @@ protected:
|
|||
return m_mouse_pos;
|
||||
}
|
||||
|
||||
int mouse_buttons () const
|
||||
{
|
||||
return m_mouse_buttons;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Commits the current configuration to the recent attributes list
|
||||
*/
|
||||
void commit_recent ();
|
||||
|
||||
/**
|
||||
* @brief Shows the toolbox widget in case one is registered for this plugin
|
||||
*/
|
||||
void show_toolbox (bool visible);
|
||||
|
||||
/**
|
||||
* @brief Finishes the edit operation
|
||||
*
|
||||
* Calls do_finish_edit() and terminates the editing operation.
|
||||
* See "do_finish_edit" for an explanation of the "accept" parameter.
|
||||
*/
|
||||
void finish_editing (bool accept);
|
||||
|
||||
/**
|
||||
* @brief Gets the toolbox widget or 0 if none is registered
|
||||
*/
|
||||
lay::EditorOptionsPage *toolbox_widget ();
|
||||
|
||||
/**
|
||||
* @brief Point snapping with detailed return value
|
||||
*/
|
||||
lay::PointSnapToObjectResult snap2_details (const db::DPoint &p) const;
|
||||
|
||||
/**
|
||||
* @brief Point snapping with detailed return value
|
||||
*/
|
||||
lay::PointSnapToObjectResult snap2_details (const db::DPoint &p, const db::DPoint &plast, bool connect) const;
|
||||
|
||||
/**
|
||||
* @brief Point snapping with detailed return value and specific angle constraint
|
||||
*/
|
||||
lay::PointSnapToObjectResult snap2_details (const db::DPoint &p, const db::DPoint &plast, lay::angle_constraint_type ac) const;
|
||||
|
||||
private:
|
||||
friend class EditableSelectionIterator;
|
||||
|
||||
|
|
@ -669,9 +711,12 @@ private:
|
|||
// The marker representing the object to be edited
|
||||
std::vector<lay::ViewObject *> m_edit_markers;
|
||||
|
||||
// The last mouse position
|
||||
// The last mouse position of the current mouse move/press/click event
|
||||
db::DPoint m_mouse_pos;
|
||||
|
||||
// The buttons flag of the current mouse move/press/click event
|
||||
int m_mouse_buttons;
|
||||
|
||||
// A flag indicating whether the mouse is inside the view
|
||||
bool m_mouse_in_view;
|
||||
|
||||
|
|
|
|||
|
|
@ -25,21 +25,23 @@
|
|||
#include "edtPathService.h"
|
||||
#include "edtPropertiesPages.h"
|
||||
#include "layLayoutView.h"
|
||||
#include "layEditorOptionsPage.h"
|
||||
#include "dbEdgeProcessor.h"
|
||||
#include "dbPolygonTools.h"
|
||||
|
||||
#if defined(HAVE_QT)
|
||||
# include "layTipDialog.h"
|
||||
# include "layTipDialog.h"
|
||||
#endif
|
||||
|
||||
#include "layEditorOptionsPages.h"
|
||||
|
||||
namespace edt
|
||||
{
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
// ShapeEditService implementation
|
||||
|
||||
const char *ShapeEditService::connection_configure_name () { return "connection-toolkit-widget-value"; }
|
||||
const char *ShapeEditService::connection_function_name () { return "connection-toolkit-widget-commit"; }
|
||||
|
||||
ShapeEditService::ShapeEditService (db::Manager *manager, lay::LayoutViewBase *view, db::ShapeIterator::flags_type shape_types)
|
||||
: edt::Service (manager, view, shape_types),
|
||||
m_layer (0), m_cv_index (0), mp_cell (0), mp_layout (0), m_combine_mode (CM_Add), m_update_edit_layer_enabled (true)
|
||||
|
|
@ -76,21 +78,19 @@ ShapeEditService::config_recent_for_layer (const db::LayerProperties &lp, int cv
|
|||
return;
|
||||
}
|
||||
|
||||
#if defined(HAVE_QT)
|
||||
lay::EditorOptionsPages *eo_pages = view ()->editor_options_pages ();
|
||||
if (!eo_pages) {
|
||||
lay::EditorOptionsPageCollection *eo_pages = view ()->editor_options_pages ();
|
||||
if (! eo_pages) {
|
||||
return;
|
||||
}
|
||||
|
||||
for (std::vector<lay::EditorOptionsPage *>::const_iterator op = eo_pages->pages ().begin (); op != eo_pages->pages ().end (); ++op) {
|
||||
if ((*op)->plugin_declaration () == plugin_declaration ()) {
|
||||
auto pages = eo_pages->editor_options_pages ();
|
||||
for (auto op = pages.begin (); op != pages.end (); ++op) {
|
||||
if ((*op)->for_plugin_declaration (plugin_declaration ())) {
|
||||
(*op)->config_recent_for_layer (dispatcher (), lp, cv_index);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
ShapeEditService::get_edit_layer ()
|
||||
{
|
||||
|
|
|
|||
|
|
@ -37,6 +37,9 @@ class ShapeEditService
|
|||
: public edt::Service
|
||||
{
|
||||
public:
|
||||
static const char *connection_configure_name ();
|
||||
static const char *connection_function_name ();
|
||||
|
||||
ShapeEditService (db::Manager *manager, lay::LayoutViewBase *view, db::ShapeIterator::flags_type shape_types);
|
||||
|
||||
protected:
|
||||
|
|
|
|||
|
|
@ -25,6 +25,7 @@
|
|||
|
||||
#include "layLayoutViewBase.h"
|
||||
#include "layConverters.h"
|
||||
#include "layEditorOptionsPage.h"
|
||||
|
||||
#if defined(HAVE_QT)
|
||||
# include "edtPropertiesPages.h"
|
||||
|
|
@ -155,7 +156,7 @@ TextService::get_text () const
|
|||
}
|
||||
|
||||
void
|
||||
TextService::do_finish_edit ()
|
||||
TextService::do_finish_edit (bool /*accept*/)
|
||||
{
|
||||
{
|
||||
db::Transaction transaction (manager (), tl::to_string (tr ("Create text")));
|
||||
|
|
@ -199,6 +200,11 @@ TextService::selection_applies (const lay::ObjectInstPath &sel) const
|
|||
bool
|
||||
TextService::configure (const std::string &name, const std::string &value)
|
||||
{
|
||||
auto tb = toolbox_widget ();
|
||||
if (tb) {
|
||||
tb->configure (name, value);
|
||||
}
|
||||
|
||||
if (name == cfg_edit_text_size) {
|
||||
double size (0);
|
||||
tl::from_string (value, size);
|
||||
|
|
|
|||
|
|
@ -47,7 +47,7 @@ public:
|
|||
virtual void do_mouse_move (const db::DPoint &p);
|
||||
virtual void do_mouse_move_inactive (const db::DPoint &p);
|
||||
virtual bool do_mouse_click (const db::DPoint &p);
|
||||
virtual void do_finish_edit ();
|
||||
virtual void do_finish_edit (bool);
|
||||
virtual void do_cancel_edit ();
|
||||
virtual bool do_activated ();
|
||||
virtual bool selection_applies (const lay::ObjectInstPath &sel) const;
|
||||
|
|
|
|||
|
|
@ -203,13 +203,29 @@ public:
|
|||
}
|
||||
|
||||
/**
|
||||
* @brief Iterates all subclasses (end)
|
||||
* @brief Iterates all child classes (end)
|
||||
*/
|
||||
tl::weak_collection<ClassBase>::const_iterator end_child_classes () const
|
||||
{
|
||||
return m_child_classes.end ();
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Iterates all subclasses (begin)
|
||||
*/
|
||||
tl::weak_collection<ClassBase>::const_iterator begin_subclasses () const
|
||||
{
|
||||
return m_subclasses.begin ();
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Iterates all subclasses (end)
|
||||
*/
|
||||
tl::weak_collection<ClassBase>::const_iterator end_subclasses () const
|
||||
{
|
||||
return m_subclasses.end ();
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Iterates all classes present (begin)
|
||||
*/
|
||||
|
|
|
|||
|
|
@ -553,8 +553,12 @@ VariantUserClassImpl::execute (const tl::ExpressionParserContext &context, tl::V
|
|||
bool ret = false;
|
||||
if (args [0].is_user ()) {
|
||||
const tl::VariantUserClassBase *ub = args [0].user_cls ();
|
||||
if (ub && ub->gsi_cls () == mp_cls) {
|
||||
ret = true;
|
||||
if (ub) {
|
||||
const gsi::ClassBase *ub_gsi = ub->gsi_cls ();
|
||||
const gsi::ClassBase *cls = mp_cls;
|
||||
while (cls && ! (ret = (ub_gsi == cls))) {
|
||||
cls = cls->base ();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -898,3 +898,19 @@ TEST(17)
|
|||
"it.add_value(17.5)").execute ();
|
||||
}
|
||||
|
||||
// is_a
|
||||
TEST(18)
|
||||
{
|
||||
tl::Eval e;
|
||||
tl::Variant v;
|
||||
v = e.parse ("var b=B.new(); b.is_a(C)").execute ();
|
||||
EXPECT_EQ (v.to_string (), std::string ("false"));
|
||||
v = e.parse ("var x=X.new(); x.is_a(X)").execute ();
|
||||
EXPECT_EQ (v.to_string (), std::string ("true"));
|
||||
// Y is not a base class of X
|
||||
v = e.parse ("var x=X.new(); x.is_a(Y)").execute ();
|
||||
EXPECT_EQ (v.to_string (), std::string ("false"));
|
||||
// X is a base class of Y
|
||||
v = e.parse ("var y=Y.new(); y.is_a(X)").execute ();
|
||||
EXPECT_EQ (v.to_string (), std::string ("true"));
|
||||
}
|
||||
|
|
|
|||
|
|
@ -62,6 +62,15 @@ PluginDeclaration::get_options (std::vector < std::pair<std::string, std::string
|
|||
options.push_back (std::pair<std::string, std::string> (cfg_images_visible, "true"));
|
||||
}
|
||||
|
||||
std::vector<std::string>
|
||||
PluginDeclaration::additional_editor_options_pages () const
|
||||
{
|
||||
std::vector<std::string> names;
|
||||
// TODO: provide in a central place instead of borrowing from the edt module
|
||||
names.push_back ("GenericEditorOptions");
|
||||
return names;
|
||||
}
|
||||
|
||||
static tl::RegisteredClass<lay::PluginDeclaration> config_decl (new img::PluginDeclaration (), 4000, "img::Plugin");
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -39,6 +39,7 @@ public:
|
|||
virtual lay::Plugin *create_plugin (db::Manager *manager, lay::Dispatcher *, lay::LayoutViewBase *view) const;
|
||||
virtual bool implements_editable (std::string &title) const;
|
||||
virtual void get_options (std::vector < std::pair<std::string, std::string> > &options) const;
|
||||
virtual std::vector<std::string> additional_editor_options_pages () const;
|
||||
};
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -419,6 +419,7 @@ Service::Service (db::Manager *manager, lay::LayoutViewBase *view)
|
|||
mp_transient_view (0),
|
||||
m_move_mode (Service::move_none),
|
||||
m_moved_landmark (0),
|
||||
m_ac (lay::AC_Global),
|
||||
m_keep_selection_for_move (false),
|
||||
m_images_visible (true),
|
||||
m_visibility_cache_valid (false)
|
||||
|
|
@ -608,12 +609,14 @@ Service::begin_move (lay::Editable::MoveMode mode, const db::DPoint &p, lay::ang
|
|||
double l = catch_distance ();
|
||||
db::DBox search_dbox = db::DBox (p, p).enlarged (db::DVector (l, l));
|
||||
|
||||
m_plast = m_p1 = p;
|
||||
m_trans = db::DTrans ();
|
||||
m_ac = lay::AC_Global;
|
||||
|
||||
// choose move mode
|
||||
if (mode == lay::Editable::Selected) {
|
||||
|
||||
m_move_mode = move_selected;
|
||||
m_p1 = p;
|
||||
m_trans = db::DTrans ();
|
||||
|
||||
selection_to_view ();
|
||||
for (std::vector <img::View *>::iterator r = m_selected_image_views.begin (); r != m_selected_image_views.end (); ++r) {
|
||||
|
|
@ -657,7 +660,6 @@ Service::begin_move (lay::Editable::MoveMode mode, const db::DPoint &p, lay::ang
|
|||
} else if (mode == lay::Editable::Any) {
|
||||
|
||||
m_move_mode = move_none;
|
||||
m_p1 = p;
|
||||
double dmin = std::numeric_limits <double>::max ();
|
||||
|
||||
const db::DUserObject *robj = find_image (p, search_dbox, l, dmin);
|
||||
|
|
@ -705,11 +707,14 @@ Service::move_transform (const db::DPoint &p, db::DFTrans tr, lay::angle_constra
|
|||
return;
|
||||
}
|
||||
|
||||
db::DTrans tr_new = db::DTrans (p - db::DPoint ()) * db::DTrans (tr) * db::DTrans (m_trans.fp_trans ()) * db::DTrans (db::DPoint () - m_p1);
|
||||
|
||||
if (m_move_mode == move_all) {
|
||||
|
||||
db::DVector dp = p - db::DPoint ();
|
||||
db::DTrans dt = tr_new * m_trans.inverted ();
|
||||
|
||||
m_current.transform (db::DTrans (dp) * db::DTrans (tr) * db::DTrans (-dp));
|
||||
m_current.transform (dt);
|
||||
m_trans = dt * m_trans;
|
||||
|
||||
// display current images' parameters
|
||||
show_message ();
|
||||
|
|
@ -718,7 +723,7 @@ Service::move_transform (const db::DPoint &p, db::DFTrans tr, lay::angle_constra
|
|||
|
||||
} else if (m_move_mode == move_selected) {
|
||||
|
||||
m_trans *= db::DTrans (m_p1 - db::DPoint ()) * db::DTrans (tr) * db::DTrans (db::DPoint () - m_p1);
|
||||
m_trans = tr_new;
|
||||
|
||||
for (std::vector<img::View *>::iterator r = m_selected_image_views.begin (); r != m_selected_image_views.end (); ++r) {
|
||||
(*r)->transform_by (db::DCplxTrans (m_trans));
|
||||
|
|
@ -734,10 +739,25 @@ Service::move (const db::DPoint &p, lay::angle_constraint_type ac)
|
|||
return;
|
||||
}
|
||||
|
||||
m_ac = ac;
|
||||
|
||||
do_move (p, ac);
|
||||
|
||||
if (m_move_mode != move_selected) {
|
||||
m_selected_image_views [0]->redraw ();
|
||||
show_message ();
|
||||
}
|
||||
|
||||
propose_move_transformation (m_trans, 2);
|
||||
}
|
||||
|
||||
void
|
||||
Service::do_move (const db::DPoint &p, lay::angle_constraint_type ac)
|
||||
{
|
||||
if (m_move_mode == move_selected) {
|
||||
|
||||
db::DVector dp = p - m_p1;
|
||||
m_p1 = p;
|
||||
db::DVector dp = p - m_plast;
|
||||
m_plast = p;
|
||||
|
||||
m_trans = db::DTrans (dp) * m_trans;
|
||||
|
||||
|
|
@ -747,6 +767,8 @@ Service::move (const db::DPoint &p, lay::angle_constraint_type ac)
|
|||
|
||||
} else if (m_move_mode == move_landmark) {
|
||||
|
||||
m_trans = db::DTrans (p - m_p1);
|
||||
|
||||
std::vector <db::DPoint> li = m_initial.landmarks ();
|
||||
for (std::vector <db::DPoint>::iterator l = li.begin (); l != li.end (); ++l) {
|
||||
*l = m_initial.matrix ().trans (*l);
|
||||
|
|
@ -770,20 +792,20 @@ Service::move (const db::DPoint &p, lay::angle_constraint_type ac)
|
|||
db::adjust_matrix (m, li, lm, adjust, int (m_moved_landmark));
|
||||
m_current.set_matrix (m * m_initial.matrix ());
|
||||
|
||||
m_selected_image_views [0]->redraw ();
|
||||
|
||||
} else {
|
||||
|
||||
if (m_move_mode == move_all) {
|
||||
|
||||
db::DVector dp = p - m_p1;
|
||||
m_p1 = p;
|
||||
db::DVector dp = p - m_plast;
|
||||
m_plast = p;
|
||||
|
||||
m_trans = db::DTrans (dp) * m_trans;
|
||||
m_current.transform (db::DTrans (dp));
|
||||
|
||||
} else {
|
||||
|
||||
m_current = m_initial;
|
||||
m_trans = db::DTrans (p - m_p1);
|
||||
|
||||
db::DVector dx (0.5 * m_current.width (), 0.5 * m_current.height ());
|
||||
db::Matrix3d it = (m_current.matrix () * db::Matrix3d::disp (-dx)).inverted ();
|
||||
|
|
@ -847,15 +869,6 @@ Service::move (const db::DPoint &p, lay::angle_constraint_type ac)
|
|||
|
||||
}
|
||||
|
||||
// display current images' parameters
|
||||
show_message ();
|
||||
|
||||
m_selected_image_views [0]->redraw ();
|
||||
|
||||
}
|
||||
|
||||
if (m_move_mode != move_selected) {
|
||||
show_message ();
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -871,7 +884,14 @@ Service::show_message ()
|
|||
*/
|
||||
}
|
||||
|
||||
void
|
||||
void
|
||||
Service::end_move (const db::DVector &v)
|
||||
{
|
||||
do_move (m_p1 + v, m_ac);
|
||||
end_move (db::DPoint (), lay::AC_Any);
|
||||
}
|
||||
|
||||
void
|
||||
Service::end_move (const db::DPoint &, lay::angle_constraint_type)
|
||||
{
|
||||
if (! m_selected_image_views.empty () && ! m_selected.empty ()) {
|
||||
|
|
|
|||
|
|
@ -359,6 +359,11 @@ public:
|
|||
*/
|
||||
virtual void end_move (const db::DPoint &p, lay::angle_constraint_type ac);
|
||||
|
||||
/**
|
||||
* @brief Terminate a "move" operation with compulsory move vector
|
||||
*/
|
||||
virtual void end_move (const db::DVector &v);
|
||||
|
||||
/**
|
||||
* @brief Return the bbox of the selection (reimplementation of lay::Editable interface)
|
||||
*/
|
||||
|
|
@ -500,8 +505,10 @@ private:
|
|||
std::set<obj_iterator> m_selected;
|
||||
// The previous selection
|
||||
std::set<obj_iterator> m_previous_selection;
|
||||
// The reference point in move mode
|
||||
// The starting point in move mode
|
||||
db::DPoint m_p1;
|
||||
// The last reference point in move mode
|
||||
db::DPoint m_plast;
|
||||
// The image object representing the image being moved as it was before it was moved
|
||||
img::Object m_initial;
|
||||
// The image object representing the image being moved
|
||||
|
|
@ -514,6 +521,8 @@ private:
|
|||
MoveMode m_move_mode;
|
||||
// The index of the landmark being moved
|
||||
size_t m_moved_landmark;
|
||||
// The last "angle constraint" (button combination) used in move
|
||||
lay::angle_constraint_type m_ac;
|
||||
// Flag indicating that we want to keep the selection after the landmark was moved
|
||||
bool m_keep_selection_for_move;
|
||||
// Flag indicating whether images are visible
|
||||
|
|
@ -523,6 +532,8 @@ private:
|
|||
std::map<const img::Object *, bool> m_visibility_cache;
|
||||
|
||||
void show_message ();
|
||||
void do_move (const db::DPoint &p, lay::angle_constraint_type ac);
|
||||
|
||||
|
||||
/**
|
||||
* @brief Select a certain image
|
||||
|
|
|
|||
|
|
@ -993,7 +993,11 @@ GSIHelpProvider::produce_class_doc (const std::string &cls) const
|
|||
<< "<!DOCTYPE language SYSTEM \"klayout_doc.dtd\">" << std::endl
|
||||
<< std::endl;
|
||||
|
||||
os << "<doc><title>" << tl::to_string (QObject::tr ("API reference - Class")) << " " << escape_xml (cls) << "</title>" << std::endl;
|
||||
os << "<doc><title>" << tl::to_string (QObject::tr ("API reference - Class")) << " " << escape_xml (cls);
|
||||
if (class_doc.hidden) {
|
||||
os << " " << tl::to_string (QObject::tr ("[internal]"));
|
||||
}
|
||||
os << "</title>" << std::endl;
|
||||
os << "<property name=\"module\" value=\"" << escape_xml (cls_obj->module ()) << "\"/>" << std::endl;
|
||||
|
||||
os << "<keyword name=\"" << escape_xml (cls) << "\"/>" << std::endl;
|
||||
|
|
@ -1006,13 +1010,15 @@ GSIHelpProvider::produce_class_doc (const std::string &cls) const
|
|||
|
||||
os << "<p><b>" << tl::to_string (QObject::tr ("Description")) << "</b>: " << escape_xml (class_doc.brief_doc) << "</p>" << std::endl;
|
||||
|
||||
std::vector<const gsi::ClassBase *> classes;
|
||||
classes.push_back (real_class (cls_obj));
|
||||
const gsi::ClassBase *act_cls_obj = real_class (cls_obj);
|
||||
|
||||
const gsi::ClassBase *base = real_class (cls_obj)->base ();
|
||||
std::vector<const gsi::ClassBase *> classes;
|
||||
classes.push_back (act_cls_obj);
|
||||
|
||||
const gsi::ClassBase *base = act_cls_obj->base ();
|
||||
if (base) {
|
||||
|
||||
const gsi::ClassBase *last_cls = real_class (cls_obj);
|
||||
const gsi::ClassBase *last_cls = act_cls_obj;
|
||||
bool all_collected = false;
|
||||
|
||||
os << "<p><b>" << tl::to_string (QObject::tr ("Class hierarchy")) << "</b>: " << make_qualified_name (cls_obj);
|
||||
|
|
@ -1032,6 +1038,7 @@ GSIHelpProvider::produce_class_doc (const std::string &cls) const
|
|||
all_collected = true;
|
||||
} else if (! all_collected) {
|
||||
// class needs to be mixed into the parent
|
||||
os << " » <a href=\"" << escape_xml (class_doc_url (base->name ())) << "\">" << escape_xml (base->name ()) << " " << tl::to_string (QObject::tr ("[internal]")) << "</a>";
|
||||
classes.push_back (base);
|
||||
}
|
||||
|
||||
|
|
@ -1051,34 +1058,90 @@ GSIHelpProvider::produce_class_doc (const std::string &cls) const
|
|||
os << "</p>" << std::endl;
|
||||
}
|
||||
|
||||
// Produce child classes
|
||||
|
||||
bool any = false;
|
||||
|
||||
for (std::vector<const gsi::ClassBase *>::const_iterator c = classes.begin (); c != classes.end (); ++c) {
|
||||
|
||||
for (tl::weak_collection<gsi::ClassBase>::const_iterator cc = (*c)->begin_child_classes (); cc != (*c)->end_child_classes (); ++cc) {
|
||||
|
||||
DocumentationParser &cdoc = cls_documentation (cc.operator-> ());
|
||||
if (! cdoc.hidden || ! cdoc.alias.empty ()) {
|
||||
|
||||
if (any) {
|
||||
os << ", ";
|
||||
} else {
|
||||
os << "<p><b>" << tl::to_string (QObject::tr ("Sub-classes")) << "</b>: ";
|
||||
any = true;
|
||||
}
|
||||
|
||||
os << "<a href=\"" << escape_xml (class_doc_url (make_qualified_name (cc.operator-> ()))) << "\">" << escape_xml (cc->name ()) << "</a>";
|
||||
|
||||
if (any) {
|
||||
os << ", ";
|
||||
} else {
|
||||
os << "<p><b>" << tl::to_string (QObject::tr ("Child classes")) << "</b>: ";
|
||||
any = true;
|
||||
}
|
||||
|
||||
os << "<a href=\""
|
||||
<< escape_xml (class_doc_url (make_qualified_name (cc.operator-> ())))
|
||||
<< "\">"
|
||||
<< escape_xml (cc->name ());
|
||||
if (cdoc.hidden && cdoc.alias.empty ()) {
|
||||
os << " " << tl::to_string (QObject::tr ("[internal]"));
|
||||
}
|
||||
os << "</a>";
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
if (any) {
|
||||
os << "</p>" << std::endl;
|
||||
}
|
||||
|
||||
// Produce subclasses (parent classes)
|
||||
|
||||
any = false;
|
||||
|
||||
for (tl::weak_collection<gsi::ClassBase>::const_iterator cc = act_cls_obj->begin_subclasses (); cc != act_cls_obj->end_subclasses (); ++cc) {
|
||||
|
||||
DocumentationParser &cdoc = cls_documentation (cc.operator-> ());
|
||||
|
||||
if (any) {
|
||||
os << ", ";
|
||||
} else {
|
||||
os << "<p><b>" << tl::to_string (QObject::tr ("Subclasses")) << "</b>: ";
|
||||
any = true;
|
||||
}
|
||||
|
||||
os << "<a href=\""
|
||||
<< escape_xml (class_doc_url (make_qualified_name (cc.operator-> ())))
|
||||
<< "\">"
|
||||
<< escape_xml (cc->name ());
|
||||
if (cdoc.hidden && cdoc.alias.empty ()) {
|
||||
os << " " << tl::to_string (QObject::tr ("[internal]"));
|
||||
}
|
||||
os << "</a>";
|
||||
|
||||
}
|
||||
|
||||
if (any) {
|
||||
os << "</p>" << std::endl;
|
||||
}
|
||||
|
||||
// Inserts an index
|
||||
|
||||
os << "<h2-index/>" << std::endl;
|
||||
|
||||
// Produce class doc body
|
||||
|
||||
if (class_doc.hidden && class_doc.alias.empty ()) {
|
||||
os << "<p><b>"
|
||||
<< tl::to_string (QObject::tr ("Note"))
|
||||
<< "</b>: "
|
||||
<< tl::to_string (QObject::tr (
|
||||
"This class is an internal class provided for technical reasons - i.e. "
|
||||
"as a placeholder class for argument binding or as an abstract interface. "
|
||||
"You should not instantiate objects of this class directly. "
|
||||
"Instead, use the subclasses listed above. "
|
||||
"Also see there for more documentation and actual incarnations of this class."
|
||||
))
|
||||
<< "</p>" << std::endl;
|
||||
}
|
||||
|
||||
os << replace_references (class_doc.doc_html (), cls_obj) << std::endl;
|
||||
|
||||
// collect the methods of the class and their hidden base classes
|
||||
|
|
@ -1116,6 +1179,8 @@ GSIHelpProvider::produce_class_doc (const std::string &cls) const
|
|||
os << "</doc>" << std::endl;
|
||||
return os.str ();
|
||||
}
|
||||
|
||||
// Produce methods brief descriptions
|
||||
|
||||
int n = 0;
|
||||
int row = 0;
|
||||
|
|
@ -1190,6 +1255,8 @@ GSIHelpProvider::produce_class_doc (const std::string &cls) const
|
|||
os << "</table>" << std::endl;
|
||||
}
|
||||
|
||||
// Produce static methods brief descriptions
|
||||
|
||||
any = false;
|
||||
|
||||
n = 0;
|
||||
|
|
@ -1230,6 +1297,8 @@ GSIHelpProvider::produce_class_doc (const std::string &cls) const
|
|||
os << "</table>" << std::endl;
|
||||
}
|
||||
|
||||
// Produce protected methods brief descriptions
|
||||
|
||||
any = false;
|
||||
|
||||
n = 0;
|
||||
|
|
@ -1272,6 +1341,8 @@ GSIHelpProvider::produce_class_doc (const std::string &cls) const
|
|||
os << "</table>" << std::endl;
|
||||
}
|
||||
|
||||
// Produce deprecated methods brief descriptions
|
||||
|
||||
any = false;
|
||||
|
||||
n = 0;
|
||||
|
|
@ -1323,6 +1394,8 @@ GSIHelpProvider::produce_class_doc (const std::string &cls) const
|
|||
os << "</table>" << std::endl;
|
||||
}
|
||||
|
||||
// Produce method details
|
||||
|
||||
n = 0;
|
||||
|
||||
os << "<a name=\"detailed\"/><h2>" << tl::to_string (QObject::tr ("Detailed description")) << "</h2>" << std::endl;
|
||||
|
|
|
|||
|
|
@ -1722,7 +1722,7 @@ MainWindow::update_editor_options_dock ()
|
|||
eo_visible = pd_sel->editable_enabled ();
|
||||
}
|
||||
if (current_view () && eo_visible) {
|
||||
lay::EditorOptionsPages *eo_pages = current_view ()->editor_options_pages ();
|
||||
lay::EditorOptionsPageCollection *eo_pages = current_view ()->editor_options_pages ();
|
||||
if (! eo_pages || ! eo_pages->has_content ()) {
|
||||
eo_visible = false;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -41,13 +41,13 @@ static lay::Dispatcher *dispatcher_instance ()
|
|||
return lay::Dispatcher::instance ();
|
||||
}
|
||||
|
||||
static tl::Variant get_config (lay::Dispatcher *dispatcher, const std::string &name)
|
||||
static tl::Variant get_config (lay::Dispatcher *dispatcher, const std::string &name, const tl::Variant &default_value)
|
||||
{
|
||||
std::string value;
|
||||
if (dispatcher->config_get (name, value)) {
|
||||
return tl::Variant (value);
|
||||
} else {
|
||||
return tl::Variant ();
|
||||
return default_value;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -86,12 +86,14 @@ Class<lay::Dispatcher> decl_Dispatcher ("lay", "Dispatcher",
|
|||
"exist. If it does and an error occurred, the error message is printed\n"
|
||||
"on stderr. In both cases, false is returned.\n"
|
||||
) +
|
||||
method_ext ("get_config", &get_config, gsi::arg ("name"),
|
||||
method_ext ("get_config", &get_config, gsi::arg ("name"), gsi::arg ("default", tl::Variant (), "nil"),
|
||||
"@brief Gets the value of a local configuration parameter\n"
|
||||
"\n"
|
||||
"@param name The name of the configuration parameter whose value shall be obtained (a string)\n"
|
||||
"\n"
|
||||
"@return The value of the parameter or nil if there is no such parameter\n"
|
||||
"@return The value of the parameter or the default value if there is no such parameter\n"
|
||||
"\n"
|
||||
"The default value has been added in version 0.30.6."
|
||||
) +
|
||||
method ("set_config", (void (lay::Dispatcher::*) (const std::string &, const std::string &)) &lay::Dispatcher::config_set, gsi::arg ("name"), gsi::arg ("value"),
|
||||
"@brief Set a local configuration parameter with the given name to the given value\n"
|
||||
|
|
|
|||
|
|
@ -1,198 +0,0 @@
|
|||
|
||||
/*
|
||||
|
||||
KLayout Layout Viewer
|
||||
Copyright (C) 2006-2025 Matthias Koefferlein
|
||||
|
||||
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 2 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 for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to the Free Software
|
||||
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
|
||||
*/
|
||||
|
||||
#if defined(HAVE_QTBINDINGS)
|
||||
|
||||
#include "gsiDeclLayEditorOptionsPage.h"
|
||||
|
||||
#include "gsiQtGuiExternals.h"
|
||||
#include "gsiQtWidgetsExternals.h" // for Qt5
|
||||
|
||||
namespace gsi
|
||||
{
|
||||
|
||||
Class<lay::EditorOptionsPage> decl_EditorOptionsPageBase (QT_EXTERNAL_BASE (QWidget) "lay", "EditorOptionsPageBase",
|
||||
method ("view", &lay::EditorOptionsPage::view,
|
||||
"@brief Gets the view object this page is associated with\n"
|
||||
) +
|
||||
method ("title", &lay::EditorOptionsPage::title,
|
||||
"@brief Gets the title string of the page\n"
|
||||
) +
|
||||
method ("order", &lay::EditorOptionsPage::order,
|
||||
"@brief Gets the order index of the page\n"
|
||||
) +
|
||||
method ("is_focus_page?", &lay::EditorOptionsPage::is_focus_page,
|
||||
"@brief Gets a flag indicating whether the page is a focus page\n"
|
||||
"See \\focus_page= for a description is this attribute.\n"
|
||||
) +
|
||||
method ("focus_page=", &lay::EditorOptionsPage::set_focus_page, gsi::arg ("flag"),
|
||||
"@brief Sets a flag indicating whether the page is a focus page\n"
|
||||
"The focus page is the page that is selected when the tab key is pressed during some plugin action.\n"
|
||||
) +
|
||||
method ("is_modal_page?", &lay::EditorOptionsPage::is_modal_page,
|
||||
"@brief Gets a flag indicating whether the page is a modal page\n"
|
||||
"See \\modal_page= for a description is this attribute.\n"
|
||||
) +
|
||||
method ("modal_page=", &lay::EditorOptionsPage::set_modal_page, gsi::arg ("flag"),
|
||||
"@brief Sets a flag indicating whether the page is a modal page\n"
|
||||
"A modal page is shown in a modal dialog upon \\show. Non-modal pages are shown in the "
|
||||
"editor options dock.\n"
|
||||
) +
|
||||
method ("show", &lay::EditorOptionsPage::show,
|
||||
"@brief Shows the page\n"
|
||||
"@return A value indicating whether the page was opened non-modal (-1), accepted (1) or rejected (0)\n"
|
||||
"Provided the page is selected because the plugin is active, this method will "
|
||||
"open a dialog to show the page if it is modal, or locate the page in the editor options "
|
||||
"dock and bring it to the front if it is non-modal.\n"
|
||||
"\n"
|
||||
"Before the page is shown, \\setup is called. When the page is dismissed (accepted), \\apply is called. "
|
||||
"You can overload these methods to transfer data to and from the configuration space or to perform other "
|
||||
"actions, not related to configuration parameters."
|
||||
) +
|
||||
method ("apply", &lay::EditorOptionsPage::apply, gsi::arg ("dispatcher"),
|
||||
"@brief Transfers data from the page to the configuration\n"
|
||||
) +
|
||||
method ("setup", &lay::EditorOptionsPage::setup, gsi::arg ("dispatcher"),
|
||||
"@brief Transfers data from the configuration to the page\n"
|
||||
),
|
||||
"@brief The plugin framework's editor options page base class\n"
|
||||
"\n"
|
||||
"This class is provided as an interface to the base class implementation for various functions.\n"
|
||||
"You can use these methods in order to pass down events to the original implementation or access\n"
|
||||
"objects not created in script space.\n"
|
||||
"\n"
|
||||
"It features some useful methods such as 'view' and provides a slot to call for triggering a data "
|
||||
"transfer ('edited').\n"
|
||||
"\n"
|
||||
"Note that even though the page class is derived from QWidget, you can call QWidget methods "
|
||||
"but not overload virtual methods from QWidget.\n"
|
||||
"\n"
|
||||
"This class has been introduced in version 0.30.4.\n"
|
||||
);
|
||||
|
||||
EditorOptionsPageImpl::EditorOptionsPageImpl (const std::string &title, int index)
|
||||
: lay::EditorOptionsPage (), m_title (title), m_index (index)
|
||||
{
|
||||
// .. nothing yet ..
|
||||
}
|
||||
|
||||
void
|
||||
EditorOptionsPageImpl::call_edited ()
|
||||
{
|
||||
lay::EditorOptionsPage::edited ();
|
||||
}
|
||||
|
||||
static void apply_fb (EditorOptionsPageImpl *ep, lay::Dispatcher *root)
|
||||
{
|
||||
ep->lay::EditorOptionsPage::apply (root);
|
||||
}
|
||||
|
||||
static void setup_fb (EditorOptionsPageImpl *ep, lay::Dispatcher *root)
|
||||
{
|
||||
ep->lay::EditorOptionsPage::setup (root);
|
||||
}
|
||||
|
||||
void
|
||||
EditorOptionsPageImpl::apply_impl (lay::Dispatcher *root)
|
||||
{
|
||||
lay::EditorOptionsPage::apply (root);
|
||||
}
|
||||
|
||||
void
|
||||
EditorOptionsPageImpl::apply (lay::Dispatcher *root)
|
||||
{
|
||||
if (f_apply.can_issue ()) {
|
||||
f_apply.issue<EditorOptionsPageImpl, lay::Dispatcher *> (&EditorOptionsPageImpl::apply_impl, root);
|
||||
} else {
|
||||
EditorOptionsPageImpl::apply_impl (root);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
EditorOptionsPageImpl::setup_impl (lay::Dispatcher *root)
|
||||
{
|
||||
lay::EditorOptionsPage::setup (root);
|
||||
}
|
||||
|
||||
void
|
||||
EditorOptionsPageImpl::setup (lay::Dispatcher *root)
|
||||
{
|
||||
if (f_setup.can_issue ()) {
|
||||
f_setup.issue<EditorOptionsPageImpl, lay::Dispatcher *> (&EditorOptionsPageImpl::setup_impl, root);
|
||||
} else {
|
||||
EditorOptionsPageImpl::setup_impl (root);
|
||||
}
|
||||
}
|
||||
|
||||
EditorOptionsPageImpl *new_editor_options_page (const std::string &title, int index)
|
||||
{
|
||||
return new EditorOptionsPageImpl (title, index);
|
||||
}
|
||||
|
||||
Class<EditorOptionsPageImpl> decl_EditorOptionsPage (decl_EditorOptionsPageBase, "lay", "EditorOptionsPage",
|
||||
constructor ("new", &new_editor_options_page, gsi::arg ("title"), gsi::arg ("index"),
|
||||
"@brief Creates a new EditorOptionsPage object\n"
|
||||
"@param title The title of the page\n"
|
||||
"@param index The position of the page in the tab bar\n"
|
||||
) +
|
||||
method ("edited", &EditorOptionsPageImpl::call_edited,
|
||||
"@brief Call this method when some entry widget has changed\n"
|
||||
"When some entry widget (for example 'editingFinished' slot of a QLineEdit), "
|
||||
"call this method to initiate a transfer of information from the page to the plugin.\n"
|
||||
) +
|
||||
// prevents infinite recursion
|
||||
method_ext ("apply", &apply_fb, gsi::arg ("dispatcher"), "@hide") +
|
||||
callback ("apply", &EditorOptionsPageImpl::apply, &EditorOptionsPageImpl::f_apply, gsi::arg ("dispatcher"),
|
||||
"@brief Reimplement this method to transfer data from the page to the configuration\n"
|
||||
"In this method, you should transfer all widget data into corresponding configuration updates.\n"
|
||||
"Use \\Dispatcher#set_config on the dispatcher object ('dispatcher' argument) to set a configuration parameter.\n"
|
||||
) +
|
||||
// prevents infinite recursion
|
||||
method_ext ("setup", &setup_fb, gsi::arg ("dispatcher"), "@hide") +
|
||||
callback ("setup", &EditorOptionsPageImpl::setup, &EditorOptionsPageImpl::f_setup, gsi::arg ("dispatcher"),
|
||||
"@brief Reimplement this method to transfer data from the configuration to the page\n"
|
||||
"In this method, you should transfer all configuration data to the widgets.\n"
|
||||
"Use \\Dispatcher#get_config on the dispatcher object ('dispatcher' argument) to get a configuration parameter "
|
||||
"and set the editing widget's state accordingly.\n"
|
||||
),
|
||||
"@brief The plugin framework's editor options page\n"
|
||||
"\n"
|
||||
"This object provides a way to establish plugin-specific editor options pages.\n"
|
||||
"\n"
|
||||
"The preferred way of communication between the page and the plugin is through "
|
||||
"configuration parameters. One advantage of this approach is that the current state is "
|
||||
"automatically persisted.\n"
|
||||
"\n"
|
||||
"For this purpose, the editor options page has two methods: 'apply' which is supposed to transfer "
|
||||
"the editor widget's state into configuration parameters. 'setup' does the inverse and transfer "
|
||||
"configuration parameters into editor widget states. Both methods are called by the system when "
|
||||
"some transfer is needed.\n"
|
||||
"\n"
|
||||
"When you want to respond to widget signals and transfer information, call \\edited "
|
||||
"in the signal slot. This will trigger a transfer (aka 'apply').\n"
|
||||
"\n"
|
||||
"This class has been introduced in version 0.30.4.\n"
|
||||
);
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
|
|
@ -87,8 +87,16 @@ ACConverter::to_string (const lay::angle_constraint_type &m)
|
|||
return "any";
|
||||
} else if (m == lay::AC_Diagonal) {
|
||||
return "diagonal";
|
||||
} else if (m == lay::AC_DiagonalOnly) {
|
||||
return "diagonal_only";
|
||||
} else if (m == lay::AC_Ortho) {
|
||||
return "ortho";
|
||||
} else if (m == lay::AC_Horizontal) {
|
||||
return "horizontal";
|
||||
} else if (m == lay::AC_Vertical) {
|
||||
return "vertical";
|
||||
} else if (m == lay::AC_Global) {
|
||||
return "global";
|
||||
} else {
|
||||
return "";
|
||||
}
|
||||
|
|
@ -102,8 +110,16 @@ ACConverter::from_string (const std::string &tt, lay::angle_constraint_type &m)
|
|||
m = lay::AC_Any;
|
||||
} else if (t == "diagonal") {
|
||||
m = lay::AC_Diagonal;
|
||||
} else if (t == "diagonal_only") {
|
||||
m = lay::AC_DiagonalOnly;
|
||||
} else if (t == "ortho") {
|
||||
m = lay::AC_Ortho;
|
||||
} else if (t == "horizontal") {
|
||||
m = lay::AC_Horizontal;
|
||||
} else if (t == "vertical") {
|
||||
m = lay::AC_Vertical;
|
||||
} else if (t == "global") {
|
||||
m = lay::AC_Global;
|
||||
} else {
|
||||
m = lay::AC_Any;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -103,6 +103,14 @@ Dispatcher::config_finalize ()
|
|||
}
|
||||
}
|
||||
|
||||
void
|
||||
Dispatcher::function (const std::string &symbol, const std::string &args)
|
||||
{
|
||||
if (mp_delegate) {
|
||||
mp_delegate->function (symbol, args);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// Writing and Reading of configuration
|
||||
|
||||
|
|
|
|||
|
|
@ -87,6 +87,14 @@ public:
|
|||
// .. this implementation does nothing ..
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Generic function call
|
||||
*/
|
||||
virtual void function (const std::string & /*symbol*/, const std::string & /*args*/)
|
||||
{
|
||||
// .. this implementation does nothing ..
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Receives configuration events
|
||||
*/
|
||||
|
|
@ -250,6 +258,7 @@ protected:
|
|||
// capture the configuration events so we can change the value of the configuration actions
|
||||
virtual bool configure (const std::string &name, const std::string &value);
|
||||
virtual void config_finalize ();
|
||||
virtual void function (const std::string &symbol, const std::string &args);
|
||||
|
||||
private:
|
||||
Dispatcher (const Dispatcher &);
|
||||
|
|
|
|||
|
|
@ -47,7 +47,7 @@ struct first_of_pair_cmp_f
|
|||
// Editable implementation
|
||||
|
||||
Editable::Editable (lay::Editables *editables)
|
||||
: mp_editables (editables)
|
||||
: mp_editables (editables), m_move_transformation_priority (-1)
|
||||
{
|
||||
if (editables) {
|
||||
editables->m_editables.push_back (this);
|
||||
|
|
@ -75,6 +75,20 @@ Editable::~Editable ()
|
|||
}
|
||||
}
|
||||
|
||||
void
|
||||
Editable::reset_proposed_move_transformation ()
|
||||
{
|
||||
m_move_transformation = db::DTrans ();
|
||||
m_move_transformation_priority = -1;
|
||||
}
|
||||
|
||||
void
|
||||
Editable::propose_move_transformation (const db::DTrans &t, unsigned int priority)
|
||||
{
|
||||
m_move_transformation = t;
|
||||
m_move_transformation_priority = priority;
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------
|
||||
// Editables implementation
|
||||
|
||||
|
|
@ -490,6 +504,9 @@ Editables::begin_move (const db::DPoint &p, lay::angle_constraint_type ac)
|
|||
cancel_edits ();
|
||||
clear_previous_selection ();
|
||||
|
||||
m_move_start = p;
|
||||
m_move_transform = db::DFTrans ();
|
||||
|
||||
m_move_selection = false;
|
||||
m_any_move_operation = false;
|
||||
|
||||
|
|
@ -567,25 +584,75 @@ Editables::begin_move (const db::DPoint &p, lay::angle_constraint_type ac)
|
|||
}
|
||||
}
|
||||
|
||||
void
|
||||
std::pair<int, db::DTrans>
|
||||
Editables::move (const db::DPoint &p, lay::angle_constraint_type ac)
|
||||
{
|
||||
int move_transformation_priority = -1;
|
||||
db::DTrans move_transformation (p - m_move_start);
|
||||
move_transformation *= db::DTrans (m_move_transform);
|
||||
|
||||
m_any_move_operation = true;
|
||||
|
||||
for (iterator e = begin (); e != end (); ++e) {
|
||||
|
||||
e->reset_proposed_move_transformation ();
|
||||
|
||||
e->move (p, ac);
|
||||
|
||||
auto pmv = e->proposed_move_transformation ();
|
||||
if (move_transformation_priority < 0 || (pmv.first >= 0 && pmv.first <= move_transformation_priority)) {
|
||||
move_transformation_priority = pmv.first;
|
||||
move_transformation = pmv.second;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
return std::make_pair (move_transformation_priority, move_transformation);
|
||||
}
|
||||
|
||||
void
|
||||
Editables::move_transform (const db::DPoint &p, db::DFTrans t, lay::angle_constraint_type ac)
|
||||
{
|
||||
m_any_move_operation = true;
|
||||
m_move_transform *= t;
|
||||
|
||||
for (iterator e = begin (); e != end (); ++e) {
|
||||
e->move_transform (p, t, ac);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
void
|
||||
Editables::end_move (const db::DVector &v, db::Transaction *transaction)
|
||||
{
|
||||
std::unique_ptr<db::Transaction> trans_holder (transaction ? transaction : new db::Transaction (manager (), tl::to_string (tr ("Move"))));
|
||||
|
||||
if (m_any_move_operation) {
|
||||
|
||||
trans_holder->open ();
|
||||
|
||||
// this dummy operation will update the screen:
|
||||
if (manager ()) {
|
||||
manager ()->queue (this, new db::Op ());
|
||||
}
|
||||
|
||||
for (iterator e = begin (); e != end (); ++e) {
|
||||
e->end_move (v);
|
||||
}
|
||||
|
||||
// clear the selection that was set previously
|
||||
if (m_move_selection) {
|
||||
clear_selection ();
|
||||
}
|
||||
|
||||
} else {
|
||||
|
||||
trans_holder->cancel ();
|
||||
edit_cancel ();
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
Editables::end_move (const db::DPoint &p, lay::angle_constraint_type ac, db::Transaction *transaction)
|
||||
{
|
||||
std::unique_ptr<db::Transaction> trans_holder (transaction ? transaction : new db::Transaction (manager (), tl::to_string (tr ("Move"))));
|
||||
|
|
|
|||
|
|
@ -326,6 +326,16 @@ public:
|
|||
// .. by default, nothing is implemented ..
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Terminate a "move" operation with compulsory shift vector
|
||||
*
|
||||
* @param v The move distance to be applied
|
||||
*/
|
||||
virtual void end_move (const db::DVector & /*v*/)
|
||||
{
|
||||
// .. by default, nothing is implemented ..
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Cancel any pending operations
|
||||
*
|
||||
|
|
@ -405,13 +415,48 @@ public:
|
|||
}
|
||||
|
||||
protected:
|
||||
friend class lay::Editables;
|
||||
|
||||
Editables *editables ()
|
||||
{
|
||||
return mp_editables;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Resets the proposed move transformation
|
||||
*
|
||||
* You should not need to call this method from an Editable implementation.
|
||||
*/
|
||||
void reset_proposed_move_transformation ();
|
||||
|
||||
/**
|
||||
* @brief Proposes a move transformation
|
||||
*
|
||||
* On "move", the Editable can propose an actual move transformation that
|
||||
* may differ from the actual move distance due to implementation-specific
|
||||
* snapping.
|
||||
*
|
||||
* This method proposes a move transformation with a given priority. The
|
||||
* Editable with the lowest priority value wins.
|
||||
*/
|
||||
void propose_move_transformation (const db::DTrans &mv, unsigned int priority);
|
||||
|
||||
/**
|
||||
* @brief Gets the proposed move transformation and priority
|
||||
*
|
||||
* @return A pair with (priority, transformation)
|
||||
*
|
||||
* The returned priority is negative if not priority was set.
|
||||
*/
|
||||
std::pair<int, db::DTrans> proposed_move_transformation () const
|
||||
{
|
||||
return std::make_pair (m_move_transformation_priority, m_move_transformation);
|
||||
}
|
||||
|
||||
private:
|
||||
Editables *mp_editables;
|
||||
int m_move_transformation_priority;
|
||||
db::DTrans m_move_transformation;
|
||||
};
|
||||
|
||||
/**
|
||||
|
|
@ -551,8 +596,16 @@ public:
|
|||
|
||||
/**
|
||||
* @brief Continue "move" operation
|
||||
*
|
||||
* The return value is the "proposed move transformation", i.e. a representative
|
||||
* one used for the actual move. As every interface may decide about the
|
||||
* actual move transformation (due to specific snapping to objects etc.), the
|
||||
* return value many be ambiguous and should be used for information purposes
|
||||
* only.
|
||||
*
|
||||
* @return A pair (priority, transformation) where priority is negative if no vector was proposed
|
||||
*/
|
||||
void move (const db::DPoint &p, lay::angle_constraint_type ac);
|
||||
std::pair<int, db::DTrans> move (const db::DPoint &p, lay::angle_constraint_type ac);
|
||||
|
||||
/**
|
||||
* @brief Transform during a move operation
|
||||
|
|
@ -567,6 +620,16 @@ public:
|
|||
*/
|
||||
void end_move (const db::DPoint &p, lay::angle_constraint_type ac, db::Transaction *transaction = 0);
|
||||
|
||||
/**
|
||||
* @brief End "move" operation with given vector
|
||||
*
|
||||
* If a transaction is given, the operation will be appended to this pending transaction
|
||||
* The Editables object takes ownership over the Transaction object.
|
||||
*
|
||||
* The vector is supposed to be taken "as is" and no snapping shall be applied.
|
||||
*/
|
||||
void end_move (const db::DVector &v, db::Transaction *transaction = 0);
|
||||
|
||||
/**
|
||||
* @brief Indicates how many objects are selected.
|
||||
*
|
||||
|
|
@ -678,6 +741,8 @@ private:
|
|||
|
||||
tl::shared_collection<lay::Editable> m_editables;
|
||||
std::set<lay::Editable *> m_enabled;
|
||||
db::DPoint m_move_start;
|
||||
db::DFTrans m_move_transform;
|
||||
bool m_move_selection;
|
||||
bool m_any_move_operation;
|
||||
db::DBox m_last_selected_point;
|
||||
|
|
|
|||
|
|
@ -20,31 +20,34 @@
|
|||
|
||||
*/
|
||||
|
||||
#if defined(HAVE_QT)
|
||||
|
||||
#include "tlInternational.h"
|
||||
#include "layEditorOptionsPage.h"
|
||||
#include "layEditorOptionsPages.h"
|
||||
#include "layLayoutViewBase.h"
|
||||
#include "tlClassRegistry.h"
|
||||
#include "tlExceptions.h"
|
||||
|
||||
#include <QApplication>
|
||||
#include <QKeyEvent>
|
||||
|
||||
namespace lay
|
||||
{
|
||||
|
||||
// ------------------------------------------------------------------
|
||||
// EditorOptionsPageCollection implementation
|
||||
|
||||
EditorOptionsPageCollection::EditorOptionsPageCollection ()
|
||||
{
|
||||
// .. nothing yet ..
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------
|
||||
// EditorOptionsPage implementation
|
||||
|
||||
EditorOptionsPage::EditorOptionsPage (lay::LayoutViewBase *view, lay::Dispatcher *dispatcher)
|
||||
: QWidget (0), mp_owner (0), m_active (true), m_focus_page (false), m_modal_page (false), mp_plugin_declaration (0), mp_dispatcher (dispatcher), mp_view (view)
|
||||
: mp_owner (0), m_active (true), m_focus_page (false), m_modal_page (false), m_toolbox_widget (false), mp_dispatcher (0), mp_view (0)
|
||||
{
|
||||
attach_events ();
|
||||
init (view, dispatcher);
|
||||
}
|
||||
|
||||
EditorOptionsPage::EditorOptionsPage ()
|
||||
: QWidget (0), mp_owner (0), m_active (true), m_focus_page (false), m_modal_page (false), mp_plugin_declaration (0), mp_dispatcher (0), mp_view (0)
|
||||
: mp_owner (0), m_active (true), m_focus_page (false), m_modal_page (false), m_toolbox_widget (false), mp_dispatcher (0), mp_view (0)
|
||||
{
|
||||
// .. nothing yet ..
|
||||
}
|
||||
|
|
@ -62,64 +65,18 @@ EditorOptionsPage::init (lay::LayoutViewBase *view, lay::Dispatcher *dispatcher)
|
|||
attach_events ();
|
||||
}
|
||||
|
||||
void
|
||||
EditorOptionsPage::edited ()
|
||||
{
|
||||
apply (dispatcher ());
|
||||
}
|
||||
|
||||
static bool is_parent_widget (QWidget *w, QWidget *parent)
|
||||
{
|
||||
while (w && w != parent) {
|
||||
w = dynamic_cast<QWidget *> (w->parent ());
|
||||
}
|
||||
return w == parent;
|
||||
}
|
||||
|
||||
bool
|
||||
EditorOptionsPage::focusNextPrevChild (bool next)
|
||||
{
|
||||
bool res = QWidget::focusNextPrevChild (next);
|
||||
|
||||
// Stop making the focus leave the page - this way we can jump back to the
|
||||
// view on "enter"
|
||||
if (res && ! is_modal_page () && ! is_parent_widget (QApplication::focusWidget (), this) && focusWidget ()) {
|
||||
focusWidget ()->setFocus ();
|
||||
}
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
void
|
||||
EditorOptionsPage::keyPressEvent (QKeyEvent *event)
|
||||
{
|
||||
BEGIN_PROTECTED
|
||||
if (! is_modal_page () && event->modifiers () == Qt::NoModifier && event->key () == Qt::Key_Return) {
|
||||
// The Return key on a non-modal page commits the values and gives back the focus
|
||||
// to the view
|
||||
apply (dispatcher ());
|
||||
view ()->set_focus ();
|
||||
event->accept ();
|
||||
} else {
|
||||
QWidget::keyPressEvent (event);
|
||||
}
|
||||
END_PROTECTED
|
||||
}
|
||||
|
||||
void
|
||||
EditorOptionsPage::set_focus ()
|
||||
{
|
||||
setFocus (Qt::TabFocusReason);
|
||||
QWidget::focusNextPrevChild (true);
|
||||
}
|
||||
|
||||
int
|
||||
EditorOptionsPage::show ()
|
||||
{
|
||||
if (mp_owner && m_active) {
|
||||
if (! m_active) {
|
||||
return -1;
|
||||
} else if (m_toolbox_widget) {
|
||||
set_focus ();
|
||||
return 1;
|
||||
} else if (mp_owner) {
|
||||
if (! is_modal_page ()) {
|
||||
mp_owner->make_page_current (this);
|
||||
return -1;
|
||||
return 1;
|
||||
} else {
|
||||
return mp_owner->exec_modal (this) ? 1 : 0;
|
||||
}
|
||||
|
|
@ -153,7 +110,7 @@ EditorOptionsPage::on_technology_changed ()
|
|||
}
|
||||
|
||||
void
|
||||
EditorOptionsPage::set_owner (EditorOptionsPages *owner)
|
||||
EditorOptionsPage::set_owner (EditorOptionsPageCollection *owner)
|
||||
{
|
||||
if (mp_owner) {
|
||||
mp_owner->unregister_page (this);
|
||||
|
|
@ -166,12 +123,16 @@ EditorOptionsPage::activate (bool active)
|
|||
{
|
||||
if (m_active != active) {
|
||||
m_active = active;
|
||||
if (mp_owner) {
|
||||
mp_owner->activate_page (this);
|
||||
if (m_active) {
|
||||
if (mp_owner) {
|
||||
mp_owner->activate_page (this);
|
||||
}
|
||||
activated ();
|
||||
} else {
|
||||
deactivated ();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
|
|
|
|||
|
|
@ -20,8 +20,6 @@
|
|||
|
||||
*/
|
||||
|
||||
#if defined(HAVE_QT)
|
||||
|
||||
#ifndef HDR_layEditorOptionsPage
|
||||
#define HDR_layEditorOptionsPage
|
||||
|
||||
|
|
@ -29,7 +27,7 @@
|
|||
|
||||
#include "tlObject.h"
|
||||
|
||||
#include <QWidget>
|
||||
#include <set>
|
||||
|
||||
namespace db
|
||||
{
|
||||
|
|
@ -44,38 +42,206 @@ class Dispatcher;
|
|||
class LayoutViewBase;
|
||||
class Plugin;
|
||||
class CellView;
|
||||
class EditorOptionsPages;
|
||||
class EditorOptionsPage;
|
||||
class EditorOptionsPageWidget;
|
||||
|
||||
/**
|
||||
* @brief The base class for a object properties page
|
||||
* @brief An interface managing a collection of EditorOptionPage objects
|
||||
*/
|
||||
class LAYBASIC_PUBLIC EditorOptionsPageCollection
|
||||
{
|
||||
public:
|
||||
EditorOptionsPageCollection ();
|
||||
virtual ~EditorOptionsPageCollection () { }
|
||||
|
||||
virtual void unregister_page (EditorOptionsPage *page) = 0;
|
||||
virtual bool has_content () const = 0;
|
||||
virtual bool has_modal_content () const = 0;
|
||||
virtual void make_page_current (EditorOptionsPage *page) = 0;
|
||||
virtual void activate_page (EditorOptionsPage *page) = 0;
|
||||
virtual void activate (const lay::Plugin *plugin) = 0;
|
||||
virtual bool exec_modal (EditorOptionsPage *page) = 0;
|
||||
virtual std::vector<lay::EditorOptionsPage *> editor_options_pages (const lay::PluginDeclaration *plugin) = 0;
|
||||
virtual std::vector<lay::EditorOptionsPage *> editor_options_pages () = 0;
|
||||
virtual lay::EditorOptionsPage *page_with_name (const std::string &name) = 0;
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief The base class for a editor options page
|
||||
*
|
||||
* The object properties page is shown in the editor options panel
|
||||
* for the active plugin.
|
||||
*
|
||||
* Pages can be toolbox widgets, i.e. they are shown in the drawing area
|
||||
* at the top of the canvas, instead of being shown in the editor options
|
||||
* panel.
|
||||
*/
|
||||
class LAYBASIC_PUBLIC EditorOptionsPage
|
||||
: public QWidget, public tl::Object
|
||||
: public tl::Object
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
/**
|
||||
* @brief Constructor
|
||||
*/
|
||||
EditorOptionsPage (lay::LayoutViewBase *view, lay::Dispatcher *dispatcher);
|
||||
|
||||
/**
|
||||
* @brief Default constructor
|
||||
*/
|
||||
EditorOptionsPage ();
|
||||
|
||||
/**
|
||||
* @brief Destructor
|
||||
*/
|
||||
virtual ~EditorOptionsPage ();
|
||||
|
||||
/**
|
||||
* @brief The title of the page
|
||||
* This title is used for the tab title the page appears
|
||||
*/
|
||||
virtual std::string title () const = 0;
|
||||
|
||||
/**
|
||||
* @brief The order in which the pages appear
|
||||
* This index specifies the position of the page. The page with the
|
||||
* lower index appears left.
|
||||
* The page with order 0 is the default page, picked when the plugin
|
||||
* becomes active.
|
||||
*/
|
||||
virtual int order () const = 0;
|
||||
|
||||
/**
|
||||
* @brief The page name
|
||||
* Giving a page name allows looking up a page by name.
|
||||
* The page name is optional and if not specified, a zero pointer
|
||||
* should be returned.
|
||||
*/
|
||||
virtual const char *name () const { return 0; }
|
||||
|
||||
/**
|
||||
* @brief A callback to apply all values
|
||||
* The page is expected to issue "config_set" calls to the dispatcher
|
||||
* to deliver the settings.
|
||||
* This callback is not used for toolbox widgets.
|
||||
*/
|
||||
virtual void apply (lay::Dispatcher * /*root*/) { }
|
||||
|
||||
/**
|
||||
* @brief A callback to setup the page
|
||||
* This callback is expected to set up the page values from
|
||||
* the configuration, stored inside the dispatcher.
|
||||
* This callback is not used for toolbox widgets.
|
||||
*/
|
||||
virtual void setup (lay::Dispatcher * /*root*/) { }
|
||||
|
||||
/**
|
||||
* @brief A callback to cancel the page edits
|
||||
* This callback is used for toolbox widgets if the user presses
|
||||
* "Escape".
|
||||
*/
|
||||
virtual void cancel () { }
|
||||
|
||||
/**
|
||||
* @brief A callback to commit the values
|
||||
* This callback is used for toolbox widgets if the user presses
|
||||
* "Enter". It can either commit values to the dispatcher
|
||||
* through "config_set", or perform other functions.
|
||||
*/
|
||||
virtual void commit (lay::Dispatcher * /*root*/) { }
|
||||
|
||||
/**
|
||||
* @brief Configure the page
|
||||
* This interface can be used by plugin implementation to transfer
|
||||
* data from the plugin to a toolbox widget. This method is not
|
||||
* used by the system directly.
|
||||
*/
|
||||
virtual void configure (const std::string & /*name*/, const std::string & /*value*/) { }
|
||||
|
||||
/**
|
||||
* @brief Called by the system to commit the current settings into some "recently used" list
|
||||
*/
|
||||
virtual void commit_recent (lay::Dispatcher * /*root*/) { }
|
||||
|
||||
/**
|
||||
* @brief Called by the system to restore recent settings for a given layer
|
||||
*/
|
||||
virtual void config_recent_for_layer (lay::Dispatcher * /*root*/, const db::LayerProperties & /*lp*/, int /*cv_index*/) { }
|
||||
|
||||
bool is_focus_page () const { return m_focus_page; }
|
||||
void set_focus_page (bool f) { m_focus_page = f; }
|
||||
void set_focus ();
|
||||
/**
|
||||
* @brief Sets the focus to the page
|
||||
* This function is called by the system to establish the focus on this page.
|
||||
*/
|
||||
virtual void set_focus () { }
|
||||
|
||||
/**
|
||||
* @brief Returns the widget for the page
|
||||
* The page itself is not a Qt object. To fetch the corresponding widget, use this method.
|
||||
*/
|
||||
virtual EditorOptionsPageWidget *widget () { return 0; }
|
||||
|
||||
/**
|
||||
* @brief Gets a value indicating whether the page is visible
|
||||
*/
|
||||
virtual bool is_visible () const { return false; }
|
||||
|
||||
/**
|
||||
* @brief Changes the visibility of the page
|
||||
*/
|
||||
virtual void set_visible (bool /*visible*/) { }
|
||||
|
||||
/**
|
||||
* @brief Returns a flag indicating whether the page is a focus page
|
||||
* Focus pages are pages that are activated when the user presses the Tab
|
||||
* key in the canvas. Toolbox widgets receive the focus and modal pages
|
||||
* are shown modally.
|
||||
*/
|
||||
bool is_focus_page () const { return m_focus_page; }
|
||||
|
||||
/**
|
||||
* @brief Sets a flag indicating whether the page is a focus page
|
||||
*/
|
||||
void set_focus_page (bool f) { m_focus_page = f; }
|
||||
|
||||
/**
|
||||
* @brief Returns a flag indicating whether the page is a modal page
|
||||
* Modal pages are shown in a modal dialog when they receive the focus.
|
||||
* Otherwise they remain invisible.
|
||||
*/
|
||||
bool is_modal_page () const { return m_modal_page; }
|
||||
|
||||
/**
|
||||
* @brief Sets a flag indicating whether the page is a modal page
|
||||
*/
|
||||
void set_modal_page (bool f) { m_modal_page = f; }
|
||||
|
||||
/**
|
||||
* @brief Returns a flag indicating whether the page is a toolbox widget
|
||||
*/
|
||||
bool is_toolbox_widget () const { return m_toolbox_widget; }
|
||||
|
||||
/**
|
||||
* @brief Sets a flag indicating whether the page is a toolbox widget
|
||||
*/
|
||||
void set_toolbox_widget (bool f) { m_toolbox_widget = f; }
|
||||
|
||||
/**
|
||||
* @brief Gets a value indicating whether the page is active
|
||||
* A page is active when the corresponding plugin is active
|
||||
*/
|
||||
bool active () const { return m_active; }
|
||||
|
||||
/**
|
||||
* @brief Activates a page
|
||||
* This function is called when the system activates a page because the
|
||||
* corresponding plugin was activate.
|
||||
*/
|
||||
void activate (bool active);
|
||||
void set_owner (EditorOptionsPages *owner);
|
||||
|
||||
/**
|
||||
* @brief Sets the owner of the page
|
||||
* This function is used by the system and must not be used otherwise.
|
||||
*/
|
||||
void set_owner (EditorOptionsPageCollection *owner);
|
||||
|
||||
/**
|
||||
* @brief Shows the editor page
|
||||
|
|
@ -83,37 +249,68 @@ public:
|
|||
*/
|
||||
int show ();
|
||||
|
||||
const lay::PluginDeclaration *plugin_declaration () const { return mp_plugin_declaration; }
|
||||
void set_plugin_declaration (const lay::PluginDeclaration *pd) { mp_plugin_declaration = pd; }
|
||||
/**
|
||||
* @brief Gets a value indicating whether the page is for that specific plugin (given by a declaration object)
|
||||
*/
|
||||
bool for_plugin_declaration (const lay::PluginDeclaration *pd)
|
||||
{
|
||||
return m_plugin_declarations.find (pd) != m_plugin_declarations.end ();
|
||||
}
|
||||
|
||||
void init (lay::LayoutViewBase *view, lay::Dispatcher *dispatcher);
|
||||
/**
|
||||
* @brief Sets the plugin the page is associated with
|
||||
* This function is used by the system and must not be used otherwise.
|
||||
*/
|
||||
void set_plugin_declaration (const lay::PluginDeclaration *pd)
|
||||
{
|
||||
m_plugin_declarations.clear ();
|
||||
m_plugin_declarations.insert (pd);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Sets the plugins the page is associated with
|
||||
* This function is used by the system and must not be used otherwise.
|
||||
*/
|
||||
void set_plugin_declarations (const std::vector<const lay::PluginDeclaration *> &pd)
|
||||
{
|
||||
m_plugin_declarations.clear ();
|
||||
m_plugin_declarations.insert (pd.begin (), pd.end ());
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Gets the dispatcher the page is connected to
|
||||
*/
|
||||
lay::Dispatcher *dispatcher () const
|
||||
{
|
||||
return mp_dispatcher;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Gets the view the page is connected to
|
||||
*/
|
||||
lay::LayoutViewBase *view () const
|
||||
{
|
||||
return mp_view;
|
||||
}
|
||||
|
||||
protected slots:
|
||||
void edited ();
|
||||
/**
|
||||
* @brief Initializes the page
|
||||
* This function is used by the system and must not be used otherwise.
|
||||
*/
|
||||
void init (lay::LayoutViewBase *view, lay::Dispatcher *dispatcher);
|
||||
|
||||
protected:
|
||||
virtual void active_cellview_changed () { }
|
||||
virtual void technology_changed (const std::string & /*tech*/) { }
|
||||
|
||||
virtual bool focusNextPrevChild (bool next);
|
||||
virtual void keyPressEvent (QKeyEvent *event);
|
||||
virtual void activated () { }
|
||||
virtual void deactivated () { }
|
||||
|
||||
private:
|
||||
EditorOptionsPages *mp_owner;
|
||||
EditorOptionsPageCollection *mp_owner;
|
||||
bool m_active;
|
||||
bool m_focus_page;
|
||||
bool m_modal_page;
|
||||
const lay::PluginDeclaration *mp_plugin_declaration;
|
||||
bool m_modal_page, m_toolbox_widget;
|
||||
std::set<const lay::PluginDeclaration *> m_plugin_declarations;
|
||||
lay::Dispatcher *mp_dispatcher;
|
||||
lay::LayoutViewBase *mp_view;
|
||||
|
||||
|
|
@ -122,8 +319,87 @@ private:
|
|||
void attach_events ();
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief A basic factory class for editor options pages
|
||||
*
|
||||
* We will use it later to provide a registration-based specialized factory
|
||||
* for Qt-enabled option pages, which we should not link here.
|
||||
*
|
||||
* A factory has a name - if the name matches a plugin name,
|
||||
* the factory is automatically requested to create a page for
|
||||
* that plugin.
|
||||
*
|
||||
* Otherwise, plugins can request additional pages through
|
||||
* "additional_editor_options_pages". This is a list of names
|
||||
* (not plugin names) of page factories. These factories will
|
||||
* be called to provide additional pages then.
|
||||
*/
|
||||
class LAYBASIC_PUBLIC EditorOptionsPageFactoryBase
|
||||
{
|
||||
public:
|
||||
EditorOptionsPageFactoryBase (const char *name)
|
||||
: m_name (name)
|
||||
{
|
||||
// .. nothing yet ..
|
||||
}
|
||||
|
||||
EditorOptionsPageFactoryBase ()
|
||||
: m_name ()
|
||||
{
|
||||
// .. nothing yet ..
|
||||
}
|
||||
|
||||
virtual ~EditorOptionsPageFactoryBase () { }
|
||||
|
||||
const std::string &name () const
|
||||
{
|
||||
return m_name;
|
||||
}
|
||||
|
||||
virtual lay::EditorOptionsPage *create_page (lay::LayoutViewBase *view, lay::Dispatcher *dispatcher) = 0;
|
||||
|
||||
private:
|
||||
std::string m_name;
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief A specialized editor options page factory class for a specific type
|
||||
*
|
||||
* Register the factory using:
|
||||
*
|
||||
* #include "tlClassRegistry.h"
|
||||
* static tl::RegisteredClass<lay::EditorOptionsPageFactoryBase> s_factory (new lay::EditorOptionsPageFactory<MyClass> (), 0, "MyClass");
|
||||
*
|
||||
* Later you can create a page from "MyName" using
|
||||
*
|
||||
* page = EditorOptionsPageFactoryBase::create_page_by_name ("MyClass", view, dispatcher);
|
||||
*/
|
||||
template <class T>
|
||||
class LAYBASIC_PUBLIC_TEMPLATE EditorOptionsPageFactory
|
||||
: public EditorOptionsPageFactoryBase
|
||||
{
|
||||
public:
|
||||
EditorOptionsPageFactory (const char *plugin_name)
|
||||
: EditorOptionsPageFactoryBase (plugin_name)
|
||||
{
|
||||
// .. nothing yet ..
|
||||
}
|
||||
|
||||
EditorOptionsPageFactory ()
|
||||
: EditorOptionsPageFactoryBase ()
|
||||
{
|
||||
// .. nothing yet ..
|
||||
}
|
||||
|
||||
virtual ~EditorOptionsPageFactory () { }
|
||||
|
||||
virtual lay::EditorOptionsPage *create_page (lay::LayoutViewBase *view, lay::Dispatcher *dispatcher)
|
||||
{
|
||||
return new T (view, dispatcher);
|
||||
}
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
#endif // defined(HAVE_QT)
|
||||
|
|
|
|||
|
|
@ -22,7 +22,6 @@
|
|||
|
||||
#include "layEditorServiceBase.h"
|
||||
#include "layEditorOptionsPage.h"
|
||||
#include "layEditorOptionsPages.h"
|
||||
#include "layViewport.h"
|
||||
#include "layLayoutViewBase.h"
|
||||
#include "laybasicConfig.h"
|
||||
|
|
@ -345,22 +344,14 @@ EditorServiceBase::activated ()
|
|||
m_active = true;
|
||||
}
|
||||
|
||||
#if defined(HAVE_QT)
|
||||
|
||||
std::vector<lay::EditorOptionsPage *>
|
||||
EditorServiceBase::editor_options_pages ()
|
||||
{
|
||||
lay::EditorOptionsPages *eo_pages = mp_view->editor_options_pages ();
|
||||
lay::EditorOptionsPageCollection *eo_pages = mp_view->editor_options_pages ();
|
||||
if (!eo_pages) {
|
||||
return std::vector<lay::EditorOptionsPage *> ();
|
||||
} else {
|
||||
std::vector<lay::EditorOptionsPage *> pages;
|
||||
for (auto p = eo_pages->pages ().begin (); p != eo_pages->pages ().end (); ++p) {
|
||||
if ((*p)->plugin_declaration () == plugin_declaration ()) {
|
||||
pages.push_back (*p);
|
||||
}
|
||||
}
|
||||
return pages;
|
||||
return eo_pages->editor_options_pages (plugin_declaration ());
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -378,50 +369,39 @@ EditorServiceBase::focus_page ()
|
|||
}
|
||||
|
||||
bool
|
||||
EditorServiceBase::key_event (unsigned int key, unsigned int buttons)
|
||||
EditorServiceBase::key_event (unsigned int key, unsigned int /*buttons*/)
|
||||
{
|
||||
if (is_active () && key == Qt::Key_Tab && buttons == 0) {
|
||||
focus_page_open ();
|
||||
return true;
|
||||
if (is_active () && (key == lay::KeyTab || key == lay::KeyBacktab)) {
|
||||
return focus_page_open () >= 0;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
bool
|
||||
EditorServiceBase::shortcut_override_event (unsigned int key, unsigned int /*buttons*/)
|
||||
{
|
||||
auto fp = focus_page ();
|
||||
return is_active ()
|
||||
&& (key == lay::KeyTab || key == lay::KeyBacktab)
|
||||
&& fp
|
||||
&& (fp->is_modal_page () || fp->is_visible ());
|
||||
}
|
||||
|
||||
int
|
||||
EditorServiceBase::focus_page_open ()
|
||||
{
|
||||
auto fp = focus_page ();
|
||||
return fp ? fp->show () : 0;
|
||||
return fp ? fp->show () : -1;
|
||||
}
|
||||
|
||||
void
|
||||
EditorServiceBase::show_error (tl::Exception &ex)
|
||||
{
|
||||
tl::error << ex.msg ();
|
||||
#if defined(HAVE_QT)
|
||||
QMessageBox::critical (ui ()->widget (), tr ("Error"), tl::to_qstring (ex.msg ()));
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
bool
|
||||
EditorServiceBase::key_event (unsigned int key, unsigned int buttons)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
void
|
||||
EditorServiceBase::show_error (tl::Exception &ex)
|
||||
{
|
||||
tl::error << ex.msg ();
|
||||
}
|
||||
|
||||
int
|
||||
EditorServiceBase::focus_page_open ()
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
#endif
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -185,6 +185,11 @@ public:
|
|||
*/
|
||||
virtual bool key_event (unsigned int /*key*/, unsigned int /*buttons*/);
|
||||
|
||||
/**
|
||||
* @brief Shortcut override event handler
|
||||
*/
|
||||
virtual bool shortcut_override_event (unsigned int /*key*/, unsigned int /*buttons*/);
|
||||
|
||||
/**
|
||||
* @brief Mouse press event handler
|
||||
*/
|
||||
|
|
@ -272,7 +277,6 @@ public:
|
|||
*/
|
||||
virtual int focus_page_open ();
|
||||
|
||||
#if defined(HAVE_QT)
|
||||
/**
|
||||
* @brief Gets the editor options pages associated with this plugin
|
||||
*/
|
||||
|
|
@ -282,7 +286,6 @@ public:
|
|||
* @brief Gets the focus page or 0 if there is none
|
||||
*/
|
||||
lay::EditorOptionsPage *focus_page ();
|
||||
#endif
|
||||
|
||||
private:
|
||||
// The marker representing the mouse cursor
|
||||
|
|
|
|||
|
|
@ -91,6 +91,8 @@ Finder::start (lay::LayoutViewBase *view, unsigned int cv_index, const std::vect
|
|||
{
|
||||
const lay::CellView &cv = view->cellview (cv_index);
|
||||
|
||||
reset_counter ();
|
||||
|
||||
m_layers = layers;
|
||||
mp_layout = &cv->layout ();
|
||||
mp_view = view;
|
||||
|
|
@ -265,7 +267,7 @@ ShapeFinder::ShapeFinder (bool point_mode, bool top_level_sel, db::ShapeIterator
|
|||
mp_prop_sel (0), m_inv_prop_sel (false), mp_progress (0),
|
||||
m_capture_all_shapes (capture_all_shapes)
|
||||
{
|
||||
m_tries = point_sel_tests;
|
||||
m_try_counter = m_tries = point_sel_tests;
|
||||
}
|
||||
|
||||
struct LPContextEqualOp
|
||||
|
|
@ -440,20 +442,29 @@ ShapeFinder::find_internal (lay::LayoutViewBase *view, unsigned int cv_index, co
|
|||
|
||||
auto flags_saved = m_flags;
|
||||
|
||||
try {
|
||||
if ((m_flags & db::ShapeIterator::Texts) != 0 && mp_text_info && ! mp_text_info->point_mode ()) {
|
||||
|
||||
if ((m_flags & db::ShapeIterator::Texts) != 0 && mp_text_info && ! mp_text_info->point_mode ()) {
|
||||
m_flags = db::ShapeIterator::Texts;
|
||||
|
||||
m_flags = db::ShapeIterator::Texts;
|
||||
try {
|
||||
|
||||
// for catching all labels we search the whole view area
|
||||
db::DBox scan_region_mu = view->viewport ().box ();
|
||||
start (view, m_cv_index, trans_mu, region_mu, scan_region_mu, min_level, max_level, layers);
|
||||
|
||||
m_flags = db::ShapeIterator::flags_type (flags_saved - db::ShapeIterator::Texts);
|
||||
|
||||
} catch (StopException) {
|
||||
// ...
|
||||
} catch (...) {
|
||||
m_flags = flags_saved;
|
||||
throw;
|
||||
}
|
||||
|
||||
m_flags = db::ShapeIterator::flags_type (flags_saved - db::ShapeIterator::Texts);
|
||||
|
||||
}
|
||||
|
||||
try {
|
||||
|
||||
// another pass with tight search box and without texts
|
||||
start (view, m_cv_index, trans_mu, region_mu, region_mu, min_level, max_level, layers);
|
||||
|
||||
|
|
@ -476,12 +487,18 @@ ShapeFinder::checkpoint ()
|
|||
if (! point_mode ()) {
|
||||
++*mp_progress;
|
||||
} else {
|
||||
if (--m_tries < 0) {
|
||||
if (--m_try_counter < 0) {
|
||||
throw StopException ();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
ShapeFinder::reset_counter ()
|
||||
{
|
||||
m_try_counter = m_tries;
|
||||
}
|
||||
|
||||
void
|
||||
ShapeFinder::visit_cell (const db::Cell &cell, const db::Box &hit_box, const db::Box &scan_box, const db::DCplxTrans &vp, const db::ICplxTrans &t, int /*level*/)
|
||||
{
|
||||
|
|
@ -814,12 +831,18 @@ InstFinder::checkpoint ()
|
|||
if (! point_mode ()) {
|
||||
++*mp_progress;
|
||||
} else {
|
||||
if (--m_tries < 0) {
|
||||
if (--m_try_counter < 0) {
|
||||
throw StopException ();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
InstFinder::reset_counter ()
|
||||
{
|
||||
m_try_counter = m_tries;
|
||||
}
|
||||
|
||||
bool
|
||||
InstFinder::consider_cell (const db::Cell &cell) const
|
||||
{
|
||||
|
|
|
|||
|
|
@ -213,6 +213,11 @@ protected:
|
|||
*/
|
||||
virtual void checkpoint () = 0;
|
||||
|
||||
/**
|
||||
* @brief Is called to reset a try counter that stops on "checkpoint"
|
||||
*/
|
||||
virtual void reset_counter () = 0;
|
||||
|
||||
private:
|
||||
void do_find (const db::Cell &cell, int level, const db::DCplxTrans &vp, const db::ICplxTrans &t);
|
||||
|
||||
|
|
@ -317,6 +322,7 @@ protected:
|
|||
}
|
||||
|
||||
virtual void checkpoint ();
|
||||
virtual void reset_counter ();
|
||||
|
||||
private:
|
||||
virtual void visit_cell (const db::Cell &cell, const db::Box &hit_box, const db::Box &scan_box, const db::DCplxTrans &vp, const db::ICplxTrans &t, int level);
|
||||
|
|
@ -338,7 +344,7 @@ private:
|
|||
const lay::TextInfo *mp_text_info;
|
||||
const std::set<db::properties_id_type> *mp_prop_sel;
|
||||
bool m_inv_prop_sel;
|
||||
int m_tries;
|
||||
int m_tries, m_try_counter;
|
||||
tl::AbsoluteProgress *mp_progress;
|
||||
std::vector<int> m_context_layers;
|
||||
std::map<db::cell_index_type, bool> m_cells_with_context;
|
||||
|
|
@ -385,6 +391,7 @@ public:
|
|||
}
|
||||
|
||||
virtual void checkpoint ();
|
||||
virtual void reset_counter ();
|
||||
|
||||
private:
|
||||
virtual void visit_cell (const db::Cell &cell, const db::Box &hit_box, const db::Box &scan_box, const db::DCplxTrans &vp, const db::ICplxTrans &t, int level);
|
||||
|
|
@ -396,7 +403,7 @@ private:
|
|||
db::cell_index_type m_topcell;
|
||||
const std::set<lay::ObjectInstPath> *mp_excludes;
|
||||
std::vector<lay::ObjectInstPath> m_founds;
|
||||
int m_tries;
|
||||
int m_tries, m_try_counter;
|
||||
bool m_full_arrays;
|
||||
bool m_enclose_insts;
|
||||
bool m_visible_layers;
|
||||
|
|
|
|||
|
|
@ -33,6 +33,7 @@
|
|||
#include "layLayoutCanvas.h"
|
||||
#include "layRedrawThread.h"
|
||||
#include "layLayoutViewBase.h"
|
||||
#include "layEditorOptionsPage.h"
|
||||
#include "layMarker.h"
|
||||
#if defined(HAVE_QT)
|
||||
# include "gtf.h"
|
||||
|
|
@ -238,7 +239,12 @@ LayoutCanvas::init_ui (QWidget *parent)
|
|||
void
|
||||
LayoutCanvas::key_event (unsigned int key, unsigned int buttons)
|
||||
{
|
||||
if (! (buttons & lay::ShiftButton)) {
|
||||
if (int (key) == lay::KeyTab || int (key) == lay::KeyBacktab) {
|
||||
auto page = first_toolbox_widget ();
|
||||
if (page) {
|
||||
page->set_focus ();
|
||||
}
|
||||
} else if (! (buttons & lay::ShiftButton)) {
|
||||
if (int (key) == lay::KeyDown) {
|
||||
down_arrow_key_pressed ();
|
||||
} else if (int (key) == lay::KeyUp) {
|
||||
|
|
@ -261,6 +267,33 @@ LayoutCanvas::key_event (unsigned int key, unsigned int buttons)
|
|||
}
|
||||
}
|
||||
|
||||
bool
|
||||
LayoutCanvas::shortcut_override_event (unsigned int key, unsigned int /*buttons*/)
|
||||
{
|
||||
if (int (key) == lay::KeyTab || int (key) == lay::KeyBacktab) {
|
||||
return first_toolbox_widget () != 0;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
lay::EditorOptionsPage *
|
||||
LayoutCanvas::first_toolbox_widget ()
|
||||
{
|
||||
auto pages = mp_view->editor_options_pages ();
|
||||
if (! pages) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
auto pv = pages->editor_options_pages ();
|
||||
for (auto p = pv.begin (); p != pv.end (); ++p) {
|
||||
if ((*p)->is_toolbox_widget () && (*p)->is_visible ()) {
|
||||
return *p;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
void
|
||||
LayoutCanvas::set_image_cache_size (size_t sz)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -50,6 +50,7 @@ namespace lay
|
|||
|
||||
class LayoutViewBase;
|
||||
class RedrawThread;
|
||||
class EditorOptionsPage;
|
||||
|
||||
/**
|
||||
* @brief A class representing one entry in the image cache
|
||||
|
|
@ -459,7 +460,10 @@ private:
|
|||
tl::Mutex m_mutex;
|
||||
|
||||
virtual void key_event (unsigned int key, unsigned int buttons);
|
||||
virtual bool shortcut_override_event (unsigned int key, unsigned int buttons);
|
||||
virtual void resize_event (unsigned int width, unsigned int height);
|
||||
lay::EditorOptionsPage *first_toolbox_widget ();
|
||||
|
||||
#if defined(HAVE_QT)
|
||||
virtual void gtf_probe ();
|
||||
virtual void paint_event ();
|
||||
|
|
|
|||
|
|
@ -400,7 +400,7 @@ LayoutViewBase::init (db::Manager *mgr)
|
|||
|
||||
mp_canvas = new lay::LayoutCanvas (this);
|
||||
|
||||
create_plugins ();
|
||||
LayoutViewBase::create_plugins ();
|
||||
}
|
||||
|
||||
void
|
||||
|
|
@ -4169,7 +4169,7 @@ LayoutViewBase::cancel_edits ()
|
|||
// the move service takes a special role here as it manages the
|
||||
// transaction for the collective move operation.
|
||||
if (mp_move_service) {
|
||||
mp_move_service->cancel ();
|
||||
mp_move_service->cancel_transaction ();
|
||||
}
|
||||
|
||||
// cancel all drag and pending edit operations such as move operations.
|
||||
|
|
@ -4186,7 +4186,7 @@ LayoutViewBase::finish_edits ()
|
|||
// the move service takes a special role here as it manages the
|
||||
// transaction for the collective move operation.
|
||||
if (mp_move_service) {
|
||||
mp_move_service->finish ();
|
||||
mp_move_service->finish_transaction ();
|
||||
}
|
||||
|
||||
// cancel all drag operations
|
||||
|
|
|
|||
|
|
@ -77,11 +77,12 @@ class MouseTracker;
|
|||
class ZoomService;
|
||||
class SelectionService;
|
||||
class MoveService;
|
||||
class EditorOptionsPage;
|
||||
class EditorOptionsPageCollection;
|
||||
|
||||
#if defined(HAVE_QT)
|
||||
class LayerControlPanel;
|
||||
class HierarchyControlPanel;
|
||||
class EditorOptionsPages;
|
||||
#endif
|
||||
|
||||
/**
|
||||
|
|
@ -351,6 +352,22 @@ public:
|
|||
// the base implementation does nothing
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Removes a notification
|
||||
*/
|
||||
virtual void remove_notification (const LayoutViewNotification & /*notification*/)
|
||||
{
|
||||
// the base implementation does nothing
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Adds an editor options page as a toolbox widget
|
||||
*/
|
||||
virtual void add_toolbox_widget (lay::EditorOptionsPage * /*toolbox_widget*/)
|
||||
{
|
||||
// the base implementation does nothing
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Gets the explicit title string of the view
|
||||
*
|
||||
|
|
@ -1899,15 +1916,15 @@ public:
|
|||
{
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @brief Gets the editor options page
|
||||
*/
|
||||
virtual lay::EditorOptionsPages *editor_options_pages ()
|
||||
virtual lay::EditorOptionsPageCollection *editor_options_pages ()
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @brief Get the current viewport
|
||||
|
|
|
|||
|
|
@ -147,11 +147,6 @@ public:
|
|||
{
|
||||
return new MouseTracker (view);
|
||||
}
|
||||
|
||||
virtual bool enable_catchall_editor_options_pages () const
|
||||
{
|
||||
return false;
|
||||
}
|
||||
};
|
||||
|
||||
static tl::RegisteredClass<lay::PluginDeclaration> tracker_decl (new MouseTrackerDeclaration (), -1000, "laybasic::MouseTrackerPlugin");
|
||||
|
|
|
|||
|
|
@ -24,12 +24,17 @@
|
|||
#include "layEditable.h"
|
||||
#include "layLayoutViewBase.h"
|
||||
#include "layEditorUtils.h"
|
||||
#include "layEditorOptionsPage.h"
|
||||
#include "laySelector.h"
|
||||
#include "laybasicConfig.h"
|
||||
|
||||
namespace lay
|
||||
{
|
||||
|
||||
LAYBASIC_PUBLIC std::string move_editor_options_name ("move-editor-options");
|
||||
LAYBASIC_PUBLIC std::string move_function_name ("move-execute");
|
||||
LAYBASIC_PUBLIC std::string move_distance_setter_name ("move-distance");
|
||||
|
||||
// -------------------------------------------------------------
|
||||
// MoveService implementation
|
||||
|
||||
|
|
@ -55,7 +60,11 @@ MoveService::deactivated ()
|
|||
EditorServiceBase::deactivated ();
|
||||
m_shift = db::DPoint ();
|
||||
mp_editables->clear_transient_selection ();
|
||||
drag_cancel ();
|
||||
|
||||
if (m_dragging) {
|
||||
// we don't just call drag_cancel() - this way avoids pending selections with the wrong coordinates
|
||||
mp_view->edit_cancel ();
|
||||
}
|
||||
}
|
||||
|
||||
bool
|
||||
|
|
@ -72,6 +81,35 @@ MoveService::configure (const std::string &name, const std::string &value)
|
|||
return false; // not taken
|
||||
}
|
||||
|
||||
void
|
||||
MoveService::function (const std::string &name, const std::string &value)
|
||||
{
|
||||
if (name == move_function_name) {
|
||||
|
||||
try {
|
||||
|
||||
db::DVector s;
|
||||
tl::from_string (value, s);
|
||||
|
||||
m_dragging = false;
|
||||
|
||||
show_toolbox (false);
|
||||
ui ()->ungrab_mouse (this);
|
||||
|
||||
mp_editables->end_move (s, mp_transaction.release ());
|
||||
|
||||
if (m_dragging_transient) {
|
||||
mp_editables->clear_selection ();
|
||||
}
|
||||
|
||||
drag_cancel ();
|
||||
|
||||
} catch (...) {
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
bool
|
||||
MoveService::key_event (unsigned int key, unsigned int buttons)
|
||||
{
|
||||
|
|
@ -79,6 +117,11 @@ MoveService::key_event (unsigned int key, unsigned int buttons)
|
|||
return true;
|
||||
}
|
||||
|
||||
if (buttons == 0 && (key == lay::KeyEnter || key == lay::KeyReturn)) {
|
||||
end_move ();
|
||||
return true;
|
||||
}
|
||||
|
||||
double dx = 0.0, dy = 0.0;
|
||||
if (int (key) == lay::KeyDown) {
|
||||
dy = -1.0;
|
||||
|
|
@ -120,14 +163,34 @@ MoveService::key_event (unsigned int key, unsigned int buttons)
|
|||
}
|
||||
}
|
||||
|
||||
int
|
||||
MoveService::focus_page_open ()
|
||||
bool
|
||||
MoveService::shortcut_override_event (unsigned int key, unsigned int buttons)
|
||||
{
|
||||
// This method is called on "Tab" by "key_event". "fp" is null as we don't have a focus page registered.
|
||||
if (is_active () && dispatcher ()) {
|
||||
dispatcher ()->menu_activated ("cm_sel_move");
|
||||
if (! m_dragging) {
|
||||
if (int (key) == lay::KeyDown ||
|
||||
int (key) == lay::KeyLeft ||
|
||||
int (key) == lay::KeyUp ||
|
||||
int (key) == lay::KeyRight) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
|
||||
return lay::EditorServiceBase::shortcut_override_event (key, buttons);
|
||||
}
|
||||
|
||||
void
|
||||
MoveService::show_toolbox (bool visible)
|
||||
{
|
||||
lay::EditorOptionsPage *tb = toolbox_widget ();
|
||||
if (tb) {
|
||||
tb->set_visible (visible);
|
||||
}
|
||||
}
|
||||
|
||||
lay::EditorOptionsPage *
|
||||
MoveService::toolbox_widget ()
|
||||
{
|
||||
return mp_view->editor_options_pages () ? mp_view->editor_options_pages ()->page_with_name (move_editor_options_name) : 0;
|
||||
}
|
||||
|
||||
bool
|
||||
|
|
@ -138,7 +201,23 @@ MoveService::mouse_move_event (const db::DPoint &p, unsigned int buttons, bool p
|
|||
if (m_dragging) {
|
||||
|
||||
set_cursor (lay::Cursor::size_all);
|
||||
mp_editables->move (p, ac_from_buttons (buttons));
|
||||
auto pmv = mp_editables->move (p, ac_from_buttons (buttons));
|
||||
|
||||
// display the proposed move transformation
|
||||
if (pmv.first >= 0) {
|
||||
|
||||
std::string pos = std::string ("dx: ") + tl::micron_to_string (pmv.second.disp ().x ()) + " dy: " + tl::micron_to_string (pmv.second.disp ().y ());
|
||||
if (pmv.second.rot () != 0) {
|
||||
pos += std::string (" ") + ((const db::DFTrans &) pmv.second).to_string ();
|
||||
}
|
||||
mp_view->message (pos);
|
||||
|
||||
lay::EditorOptionsPage *tb = toolbox_widget ();
|
||||
if (tb) {
|
||||
tb->configure (move_distance_setter_name, pmv.second.disp ().to_string ());
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
} else if (prio) {
|
||||
|
||||
|
|
@ -295,6 +374,14 @@ MoveService::start_move (db::Transaction *transaction, bool transient_selection)
|
|||
return handle_click (pstart, 0, drag_transient, trans_holder.release ());
|
||||
}
|
||||
|
||||
void
|
||||
MoveService::end_move ()
|
||||
{
|
||||
if (m_dragging) {
|
||||
handle_click (m_mouse_pos, 0, false, 0);
|
||||
}
|
||||
}
|
||||
|
||||
bool
|
||||
MoveService::handle_click (const db::DPoint &p, unsigned int buttons, bool drag_transient, db::Transaction *transaction)
|
||||
{
|
||||
|
|
@ -313,6 +400,8 @@ MoveService::handle_click (const db::DPoint &p, unsigned int buttons, bool drag_
|
|||
|
||||
m_dragging = true;
|
||||
m_dragging_transient = drag_transient;
|
||||
|
||||
show_toolbox (true);
|
||||
ui ()->grab_mouse (this, false);
|
||||
|
||||
m_shift = db::DPoint ();
|
||||
|
|
@ -325,7 +414,9 @@ MoveService::handle_click (const db::DPoint &p, unsigned int buttons, bool drag_
|
|||
|
||||
m_dragging = false;
|
||||
|
||||
show_toolbox (false);
|
||||
ui ()->ungrab_mouse (this);
|
||||
|
||||
mp_editables->end_move (p, ac_from_buttons (buttons), mp_transaction.release ());
|
||||
|
||||
if (m_dragging_transient) {
|
||||
|
|
@ -343,13 +434,14 @@ MoveService::drag_cancel ()
|
|||
{
|
||||
m_shift = db::DPoint ();
|
||||
if (m_dragging) {
|
||||
show_toolbox (false);
|
||||
ui ()->ungrab_mouse (this);
|
||||
m_dragging = false;
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
MoveService::cancel ()
|
||||
MoveService::cancel_transaction ()
|
||||
{
|
||||
if (m_dragging) {
|
||||
if (mp_transaction.get ()) {
|
||||
|
|
@ -360,7 +452,7 @@ MoveService::cancel ()
|
|||
}
|
||||
|
||||
void
|
||||
MoveService::finish ()
|
||||
MoveService::finish_transaction ()
|
||||
{
|
||||
if (m_dragging) {
|
||||
mp_transaction.reset (0);
|
||||
|
|
@ -383,6 +475,14 @@ public:
|
|||
{
|
||||
return new MoveService (view);
|
||||
}
|
||||
|
||||
virtual std::vector<std::string> additional_editor_options_pages () const
|
||||
{
|
||||
std::vector<std::string> names;
|
||||
// TODO: provide in a central place instead of borrowing from the edt module
|
||||
names.push_back ("GenericEditorOptions");
|
||||
return names;
|
||||
}
|
||||
};
|
||||
|
||||
static tl::RegisteredClass<lay::PluginDeclaration> move_service_decl (new MoveServiceDeclaration (), -970, "laybasic::MoveServicePlugin");
|
||||
|
|
|
|||
|
|
@ -31,6 +31,10 @@
|
|||
|
||||
namespace lay {
|
||||
|
||||
LAYBASIC_PUBLIC extern std::string move_editor_options_name;
|
||||
LAYBASIC_PUBLIC extern std::string move_function_name;
|
||||
LAYBASIC_PUBLIC extern std::string move_distance_setter_name;
|
||||
|
||||
class LayoutViewBase;
|
||||
|
||||
class LAYBASIC_PUBLIC MoveService :
|
||||
|
|
@ -41,10 +45,12 @@ public:
|
|||
~MoveService ();
|
||||
|
||||
bool start_move (db::Transaction *transaction = 0, bool transient_selection = false);
|
||||
void end_move ();
|
||||
|
||||
bool configure (const std::string &name, const std::string &value);
|
||||
void finish ();
|
||||
void cancel ();
|
||||
void function (const std::string &name, const std::string &value);
|
||||
void finish_transaction ();
|
||||
void cancel_transaction ();
|
||||
|
||||
private:
|
||||
virtual bool mouse_press_event (const db::DPoint &p, unsigned int buttons, bool prio);
|
||||
|
|
@ -54,9 +60,11 @@ private:
|
|||
virtual bool mouse_release_event (const db::DPoint &p, unsigned int /*buttons*/, bool prio);
|
||||
virtual bool wheel_event (int delta, bool horizontal, const db::DPoint &p, unsigned int buttons, bool prio);
|
||||
virtual bool key_event (unsigned int key, unsigned int buttons);
|
||||
virtual bool shortcut_override_event (unsigned int key, unsigned int buttons);
|
||||
virtual void drag_cancel ();
|
||||
virtual void deactivated ();
|
||||
int focus_page_open ();
|
||||
void show_toolbox (bool visible);
|
||||
lay::EditorOptionsPage *toolbox_widget ();
|
||||
|
||||
bool handle_click (const db::DPoint &p, unsigned int buttons, bool drag_transient, db::Transaction *transaction);
|
||||
|
||||
|
|
|
|||
|
|
@ -30,6 +30,7 @@
|
|||
|
||||
#include "layPlugin.h"
|
||||
#include "layDispatcher.h"
|
||||
#include "layEditorOptionsPage.h"
|
||||
#include "tlExceptions.h"
|
||||
#include "tlClassRegistry.h"
|
||||
|
||||
|
|
@ -317,6 +318,67 @@ PluginDeclaration::register_plugin ()
|
|||
}
|
||||
}
|
||||
|
||||
std::string
|
||||
PluginDeclaration::name () const
|
||||
{
|
||||
auto plugin_reg = tl::Registrar<lay::PluginDeclaration>::get_instance ();
|
||||
for (auto i = plugin_reg->begin (); i != plugin_reg->end (); ++i) {
|
||||
if (i.operator-> () == this) {
|
||||
return i.current_name ();
|
||||
}
|
||||
}
|
||||
|
||||
return std::string ();
|
||||
}
|
||||
|
||||
void
|
||||
PluginDeclaration::get_editor_options_pages (std::vector<lay::EditorOptionsPage *> &pages, lay::LayoutViewBase *view, lay::Dispatcher *dispatcher) const
|
||||
{
|
||||
std::string n = name ();
|
||||
if (n.empty ()) {
|
||||
return;
|
||||
}
|
||||
|
||||
auto reg = tl::Registrar<lay::EditorOptionsPageFactoryBase>::get_instance ();
|
||||
for (auto i = reg->begin (); i != reg->end (); ++i) {
|
||||
lay::EditorOptionsPage *page = 0;
|
||||
if (i->name () == n) {
|
||||
page = i->create_page (view, dispatcher);
|
||||
if (page) {
|
||||
page->set_plugin_declaration (this);
|
||||
}
|
||||
}
|
||||
if (page) {
|
||||
pages.push_back (page);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
PluginDeclaration::get_additional_editor_options_pages (std::vector<EditorOptionsPage *> &pages, LayoutViewBase *view, Dispatcher *dispatcher, const std::map<std::string, std::vector<const lay::PluginDeclaration *> > &names)
|
||||
{
|
||||
std::set<std::string> names_seen;
|
||||
|
||||
auto reg = tl::Registrar<lay::EditorOptionsPageFactoryBase>::get_instance ();
|
||||
for (auto i = reg->begin (); i != reg->end (); ++i) {
|
||||
auto n = names.find (i->name ());
|
||||
if (n != names.end ()) {
|
||||
names_seen.insert (i->name ());
|
||||
lay::EditorOptionsPage *page = i->create_page (view, dispatcher);
|
||||
if (page) {
|
||||
page->set_plugin_declarations (n->second);
|
||||
pages.push_back (page);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for (auto i = names.begin (); i != names.end (); ++i) {
|
||||
if (names_seen.find (i->first) == names_seen.end ()) {
|
||||
tl::warn << tl::to_string (tr ("Cannot find additional editor options page: ")) << i->first;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------
|
||||
// Plugin implementation
|
||||
|
||||
|
|
@ -523,6 +585,15 @@ Plugin::do_config_set (const std::string &name, const std::string &value, bool f
|
|||
return false;
|
||||
}
|
||||
|
||||
void
|
||||
Plugin::call_function (const std::string &symbol, const std::string &args)
|
||||
{
|
||||
function (symbol, args);
|
||||
for (tl::weak_collection<Plugin>::iterator c = m_children.begin (); c != m_children.end (); ++c) {
|
||||
c->call_function (symbol, args);
|
||||
}
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------------------------------------------
|
||||
// Menu item generators
|
||||
|
||||
|
|
|
|||
|
|
@ -51,9 +51,9 @@ class ViewService;
|
|||
class Editable;
|
||||
class Drawing;
|
||||
class TechnologyComponentProvider;
|
||||
class EditorOptionsPage;
|
||||
#if defined(HAVE_QT)
|
||||
class Browser;
|
||||
class EditorOptionsPage;
|
||||
class ConfigPage;
|
||||
#endif
|
||||
|
||||
|
|
@ -170,6 +170,14 @@ public:
|
|||
*/
|
||||
virtual ~PluginDeclaration ();
|
||||
|
||||
/**
|
||||
* @brief Gets the name under which the declaration was registered
|
||||
*
|
||||
* This is the name used in tl::RegisteredClass.
|
||||
* If the plugin declaration is not registered, an empty string is returned.
|
||||
*/
|
||||
std::string name () const;
|
||||
|
||||
/**
|
||||
* @brief This method is supposed to deliver the option names available
|
||||
*
|
||||
|
|
@ -323,7 +331,6 @@ public:
|
|||
return false;
|
||||
}
|
||||
|
||||
#if defined(HAVE_QT)
|
||||
/**
|
||||
* @brief Gets the editor options pages
|
||||
*
|
||||
|
|
@ -331,24 +338,26 @@ public:
|
|||
* and these will be shown in tabs inside this widget.
|
||||
*
|
||||
* The new pages are returned in the "pages" vector. The layout view will take ownership of these pages.
|
||||
*
|
||||
* The default implementation collects pages registered through editor options page factories.
|
||||
*/
|
||||
virtual void get_editor_options_pages (std::vector<lay::EditorOptionsPage *> & /*pages*/, lay::LayoutViewBase * /*view*/, lay::Dispatcher * /*dispatcher*/) const
|
||||
{
|
||||
// .. no pages in the default implementation ..
|
||||
}
|
||||
virtual void get_editor_options_pages (std::vector<lay::EditorOptionsPage *> &pages, lay::LayoutViewBase *view, lay::Dispatcher *dispatcher) const;
|
||||
|
||||
/**
|
||||
* @brief Gets a value indicating whether "catchall" editor options pages shall be included
|
||||
*
|
||||
* "catchall" editor options pages are ones that are unspecific and render a null "plugin_declaration".
|
||||
* A plugin can choose to include these pages if it listens to global configuration events.
|
||||
* Otherwise it should return false here to suppress these pages.
|
||||
* @brief Gets pages created from registered factories by name
|
||||
*/
|
||||
virtual bool enable_catchall_editor_options_pages () const
|
||||
static void get_additional_editor_options_pages (std::vector<lay::EditorOptionsPage *> &pages, lay::LayoutViewBase *view, lay::Dispatcher *dispatcher, const std::map<std::string, std::vector<const lay::PluginDeclaration *> > &names);
|
||||
|
||||
/**
|
||||
* @brief Returns a list of editor options pages that the plugin wants to inherit
|
||||
*
|
||||
* In addition to providing pages through "get_editor_options_pages", the plugin can request pages
|
||||
* from globally registered factories by name.
|
||||
*/
|
||||
virtual std::vector<std::string> additional_editor_options_pages () const
|
||||
{
|
||||
return true;
|
||||
return std::vector<std::string> ();
|
||||
}
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @brief Tells if the plugin implements a "lay::ViewService" active mouse mode
|
||||
|
|
@ -744,6 +753,13 @@ public:
|
|||
// .. this implementation does nothing ..
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Generic function call
|
||||
*
|
||||
* This method calls "function" on this plugin and all the children.
|
||||
*/
|
||||
virtual void call_function (const std::string &symbol, const std::string &args);
|
||||
|
||||
#if defined(HAVE_QT)
|
||||
/**
|
||||
* @brief Return the lay::Browser interface if this object has one
|
||||
|
|
@ -859,6 +875,17 @@ protected:
|
|||
// .. the default implementation does nothing ..
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Implements a generic function call
|
||||
*
|
||||
* This method can be used to establish a communication between a properties page and
|
||||
* a plugin for example.
|
||||
*/
|
||||
virtual void function (const std::string & /*symbol*/, const std::string & /*args*/)
|
||||
{
|
||||
// .. this implementation does nothing ..
|
||||
}
|
||||
|
||||
private:
|
||||
Plugin (const Plugin &);
|
||||
Plugin &operator= (const Plugin &);
|
||||
|
|
|
|||
|
|
@ -332,11 +332,6 @@ public:
|
|||
{
|
||||
return new SelectionService (view);
|
||||
}
|
||||
|
||||
virtual bool enable_catchall_editor_options_pages () const
|
||||
{
|
||||
return false;
|
||||
}
|
||||
};
|
||||
|
||||
static tl::RegisteredClass<lay::PluginDeclaration> selection_service_decl (new SelectionServiceDeclaration (), -980, "laybasic::SelectionServicePlugin");
|
||||
|
|
|
|||
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue