mirror of https://github.com/KLayout/klayout.git
Enabling toolbox widgets for box service. Plus add-on: pressing Shift while dragging a box makes it centered.
This commit is contained in:
parent
900ac4bc0f
commit
6b5dbb1442
|
|
@ -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,46 @@ 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 it reflects the current
|
||||
if (m_p2.x () < m_p1.x ()) {
|
||||
dim.set_x (-fabs (dim.x ()));
|
||||
}
|
||||
if (m_p2.y () < m_p1.y ()) {
|
||||
dim.set_y (-fabs (dim.y ()));
|
||||
}
|
||||
} else {
|
||||
dim = db::DVector (fabs (dim.x ()) * 0.5, fabs (dim.y ()) * 0.5);
|
||||
}
|
||||
m_p2 = m_p1 + dim;
|
||||
|
||||
finish_editing ();
|
||||
|
||||
} 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 +119,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 ());
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
|
@ -109,12 +157,13 @@ void
|
|||
BoxService::do_mouse_move (const db::DPoint &p)
|
||||
{
|
||||
// snap to square if Ctrl button is pressed
|
||||
bool snap_square = alt_ac () == lay::AC_Diagonal;
|
||||
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 ();
|
||||
|
||||
|
|
@ -152,6 +201,7 @@ BoxService::do_mouse_move (const db::DPoint &p)
|
|||
|
||||
set_cursor (lay::Cursor::cross);
|
||||
m_p2 = ps;
|
||||
m_centered = centered;
|
||||
update_marker ();
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
|
|
@ -48,9 +51,11 @@ public:
|
|||
virtual void do_finish_edit ();
|
||||
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"
|
||||
|
|
@ -898,6 +899,82 @@ EditorOptionsInstPCellParam::update_pcell_parameters (const std::vector <tl::Var
|
|||
}
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------
|
||||
// Box Toolbox widget
|
||||
|
||||
BoxToolkitWidget::BoxToolkitWidget (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);
|
||||
}
|
||||
|
||||
BoxToolkitWidget::~BoxToolkitWidget ()
|
||||
{
|
||||
// .. nothing yet ..
|
||||
}
|
||||
|
||||
std::string
|
||||
BoxToolkitWidget::title () const
|
||||
{
|
||||
return "Box Options";
|
||||
}
|
||||
|
||||
void
|
||||
BoxToolkitWidget::deactivated ()
|
||||
{
|
||||
hide ();
|
||||
}
|
||||
|
||||
void
|
||||
BoxToolkitWidget::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
|
||||
BoxToolkitWidget::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 (...) {
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------
|
||||
// Registrations
|
||||
|
||||
|
|
@ -909,6 +986,9 @@ static tl::RegisteredClass<lay::EditorOptionsPageFactoryBase> s_factory_paths (n
|
|||
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<BoxToolkitWidget> (), 0);
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
|
|
|
|||
|
|
@ -36,6 +36,7 @@
|
|||
|
||||
class QTabWidget;
|
||||
class QLabel;
|
||||
class QHBoxLayout;
|
||||
|
||||
namespace Ui
|
||||
{
|
||||
|
|
@ -55,6 +56,7 @@ namespace lay
|
|||
class Dispatcher;
|
||||
class LayoutViewBase;
|
||||
class Plugin;
|
||||
class DecoratedLineEdit;
|
||||
}
|
||||
|
||||
namespace edt
|
||||
|
|
@ -193,6 +195,29 @@ private:
|
|||
virtual void technology_changed (const std::string &);
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief The toolbox widget for boxes
|
||||
*/
|
||||
class BoxToolkitWidget
|
||||
: public lay::EditorOptionsPageWidget
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
BoxToolkitWidget (lay::LayoutViewBase *view, lay::Dispatcher *dispatcher);
|
||||
~BoxToolkitWidget ();
|
||||
|
||||
virtual std::string title () 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;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
|
|
|
|||
|
|
@ -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),
|
||||
|
|
@ -902,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) {
|
||||
|
||||
|
|
@ -938,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) {
|
||||
|
|
@ -952,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 ();
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -984,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 ();
|
||||
return true;
|
||||
} else {
|
||||
return false;
|
||||
|
|
@ -1001,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));
|
||||
|
|
@ -1022,6 +1027,17 @@ Service::key_event (unsigned int key, unsigned int buttons)
|
|||
}
|
||||
}
|
||||
|
||||
void
|
||||
Service::finish_editing ()
|
||||
{
|
||||
do_finish_edit ();
|
||||
|
||||
m_editing = false;
|
||||
show_toolbox (false);
|
||||
set_edit_marker (0);
|
||||
m_alt_ac = lay::AC_Global;
|
||||
}
|
||||
|
||||
void
|
||||
Service::activated ()
|
||||
{
|
||||
|
|
@ -1749,6 +1765,7 @@ void
|
|||
Service::begin_edit (const db::DPoint &p)
|
||||
{
|
||||
do_begin_edit (p);
|
||||
show_toolbox (true);
|
||||
m_editing = true;
|
||||
}
|
||||
|
||||
|
|
@ -2055,6 +2072,33 @@ Service::commit_recent ()
|
|||
}
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
// -------------------------------------------------------------
|
||||
// Implementation of EditableSelectionIterator
|
||||
|
||||
|
|
|
|||
|
|
@ -650,11 +650,33 @@ 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.
|
||||
*/
|
||||
void finish_editing ();
|
||||
|
||||
/**
|
||||
* @brief Gets the toolbox widget or 0 if none is registered
|
||||
*/
|
||||
lay::EditorOptionsPage *toolbox_widget ();
|
||||
|
||||
/**
|
||||
* @brief Point snapping with detailed return value
|
||||
*/
|
||||
|
|
@ -685,9 +707,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;
|
||||
|
||||
|
|
|
|||
Loading…
Reference in New Issue