Enabling toolkit widgets for rulers

This commit is contained in:
Matthias Koefferlein 2026-01-17 01:05:56 +01:00
parent 6b5dbb1442
commit c2c941078d
11 changed files with 337 additions and 23 deletions

View File

@ -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 \

View File

@ -0,0 +1,127 @@
/*
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_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 {
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::function_name (), db::DVector (dx, dy).to_string ());
} catch (...) {
}
}
void
ToolkitWidget::configure (const std::string &name, const std::string &value)
{
if (name == ant::Service::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
// toolkit widgets
static tl::RegisteredClass<lay::EditorOptionsPageFactoryBase> s_tookit_widget_factory (new lay::EditorOptionsPageFactory<ToolkitWidget> ("ant::Plugin"), 0);
}
#endif

View File

@ -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;
};
}
#endif
#endif

View File

@ -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,10 @@ 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::configure_name () { return "ant-toolkit-widget-value"; }
const char *Service::function_name () { return "ant-toolkit-widget-commit"; }
Service::Service (db::Manager *manager, lay::LayoutViewBase *view)
: lay::EditorServiceBase (view),
lay::Drawing (1/*number of planes*/, view->drawings ()),
@ -1169,6 +1174,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 +1264,7 @@ void
Service::drag_cancel ()
{
if (m_drawing) {
show_toolbox (false);
ui ()->ungrab_mouse (this);
m_drawing = false;
}
@ -1981,6 +2002,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);
}
@ -2033,6 +2055,63 @@ 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 == 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 (...) {
}
}
}
bool
Service::mouse_move_event (const db::DPoint &p, unsigned int buttons, bool prio)
{
@ -2074,6 +2153,17 @@ Service::mouse_move_event (const db::DPoint &p, unsigned int buttons, bool prio)
}
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) {
tb->configure (configure_name (), delta.to_string ());
}
mp_active_ruler->redraw ();
show_message ();

View File

@ -197,6 +197,11 @@ Q_OBJECT
public:
typedef lay::AnnotationShapes::iterator obj_iterator;
// for communicating with the toolbox widget
static const char *editor_options_name ();
static const char *configure_name ();
static const char *function_name ();
/**
* The current move mode:
* MoveNone - not moving
@ -503,10 +508,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)
*/
@ -611,6 +621,9 @@ private:
const ant::Template &current_template () const;
void show_toolbox (bool visible);
lay::EditorOptionsPage *toolbox_widget ();
void show_message ();
/**

View File

@ -80,13 +80,9 @@ BoxService::function (const std::string &name, const std::string &value)
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 ()));
}
// 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);
}

View File

@ -987,7 +987,7 @@ static tl::RegisteredClass<lay::EditorOptionsPageFactoryBase> s_factory_insts (n
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);
static tl::RegisteredClass<lay::EditorOptionsPageFactoryBase> s_box_tookit_widget_factory (new lay::EditorOptionsPageFactory<BoxToolkitWidget> ("edt::Service(Boxes)"), 0);
}

View File

@ -176,12 +176,18 @@ MoveService::shortcut_override_event (unsigned int key, unsigned int buttons)
void
MoveService::show_toolbox (bool visible)
{
lay::EditorOptionsPage *op = mp_view->editor_options_pages () ? mp_view->editor_options_pages ()->page_with_name (move_editor_options_name) : 0;
if (op) {
op->set_visible (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
MoveService::mouse_move_event (const db::DPoint &p, unsigned int buttons, bool prio)
{
@ -201,12 +207,9 @@ MoveService::mouse_move_event (const db::DPoint &p, unsigned int buttons, bool p
}
mp_view->message (pos);
lay::EditorOptionsPage *toolbox_widget = 0;
if (mp_view->editor_options_pages ()) {
toolbox_widget = mp_view->editor_options_pages ()->page_with_name (move_editor_options_name);
}
if (toolbox_widget) {
toolbox_widget->configure (move_distance_setter_name, pmv.second.disp ().to_string ());
lay::EditorOptionsPage *tb = toolbox_widget ();
if (tb) {
tb->configure (move_distance_setter_name, pmv.second.disp ().to_string ());
}
}

View File

@ -63,6 +63,7 @@ private:
virtual void drag_cancel ();
virtual void deactivated ();
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);

View File

@ -254,10 +254,22 @@ EditorOptionsPages::update (lay::EditorOptionsPage *page)
}
for (auto p = sorted_pages.begin (); p != sorted_pages.end (); ++p) {
if ((*p)->active ()) {
if ((*p)->is_toolbox_widget ()) {
mp_view->add_toolbox_widget (*p);
} else if (! (*p)->is_modal_page ()) {
if ((*p)->is_toolbox_widget ()) {
// NOTE: toolbox widgets are always created, but hidden if the
// page is not active. However, even inactive pages can become
// visible, if needed. The "move" plugin does that if used from
// externally.
if (! (*p)->active ()) {
(*p)->set_visible (false);
}
mp_view->add_toolbox_widget (*p);
} else if ((*p)->active ()) {
if (! (*p)->is_modal_page ()) {
if ((*p) == page) {
index = mp_pages->count ();
}
@ -268,9 +280,11 @@ EditorOptionsPages::update (lay::EditorOptionsPage *page)
}
mp_modal_pages->add_page (*p);
}
} else {
(*p)->setParent (0);
}
}
if (index < 0) {

View File

@ -111,6 +111,6 @@ MoveEditorOptionsPage::configure (const std::string &name, const std::string &va
}
// registers the factory for the move editor options page
static tl::RegisteredClass<lay::EditorOptionsPageFactoryBase> s_factory (new lay::EditorOptionsPageFactory<MoveEditorOptionsPage> (), 0);
static tl::RegisteredClass<lay::EditorOptionsPageFactoryBase> s_factory (new lay::EditorOptionsPageFactory<MoveEditorOptionsPage> ("laybasic::MoveServicePlugin"), 0);
}