diff --git a/src/lay/lay/SearchReplaceConfigPage.ui b/src/lay/lay/SearchReplaceConfigPage.ui index 10d32349e..dc8b0a25b 100644 --- a/src/lay/lay/SearchReplaceConfigPage.ui +++ b/src/lay/lay/SearchReplaceConfigPage.ui @@ -1,7 +1,8 @@ - + + SearchReplaceConfigPage - - + + 0 0 @@ -9,94 +10,34 @@ 158 - + Search Result Browser Configuration - - - 9 - - + + 6 + + 9 + - - + + Search Result Browser Configuration - - - 9 - - + + 6 - - - - µm - - - - - - - false - - - - - - - Maximum number of items to show - - - - - - - Window - - - - - - - - Don't change - - - - - Fit context cell - - - - - Fit marker with margin .. - - - - - Center marker - - - - - Center marker with size .. - - - - - + - + Qt::Horizontal - + QSizePolicy::Minimum - + 10 21 @@ -104,18 +45,71 @@ - - + + + + + + + + Don't change + + + + + Fit context cell + + + + + Fit marker with margin .. + + + + + Center marker + + + + + Center marker with size .. + + + + + + + + Window + + + + + + + + + + Maximum number of items to show + + - + + + + lay::MarginWidget + QWidget +
layWidgets.h
+ 1 +
+
cbx_window - le_window le_max_items diff --git a/src/lay/lay/laySearchReplaceConfigPage.cc b/src/lay/lay/laySearchReplaceConfigPage.cc index 946ec0034..e0e93affb 100644 --- a/src/lay/lay/laySearchReplaceConfigPage.cc +++ b/src/lay/lay/laySearchReplaceConfigPage.cc @@ -87,9 +87,9 @@ SearchReplaceConfigPage::setup (lay::Dispatcher *root) cbx_window->setCurrentIndex (int (wmode)); // window dimension - double wdim = 1.0; - root->config_get (cfg_sr_window_dim, wdim); - le_window->setText (tl::to_qstring (tl::to_string (wdim))); + std::string wdim_str; + root->config_get (cfg_sr_window_dim, wdim_str); + mrg_window->set_margin (lay::Margin::from_string (wdim_str)); // max. instance count unsigned int max_item_count = 1000; @@ -103,20 +103,19 @@ SearchReplaceConfigPage::setup (lay::Dispatcher *root) void SearchReplaceConfigPage::window_changed (int m) { - le_window->setEnabled (m == int (SearchReplaceDialog::FitMarker) || m == int (SearchReplaceDialog::CenterSize)); + mrg_window->setEnabled (m == int (SearchReplaceDialog::FitMarker) || m == int (SearchReplaceDialog::CenterSize)); } void SearchReplaceConfigPage::commit (lay::Dispatcher *root) { - double dim = 1.0; - tl::from_string_ext (tl::to_string (le_window->text ()), dim); + lay::Margin dim = mrg_window->get_margin (); unsigned int max_item_count = 1000; tl::from_string_ext (tl::to_string (le_max_items->text ()), max_item_count); root->config_set (cfg_sr_window_mode, SearchReplaceDialog::window_type (cbx_window->currentIndex ()), SearchReplaceWindowModeConverter ()); - root->config_set (cfg_sr_window_dim, dim); + root->config_set (cfg_sr_window_dim, dim.to_string ()); root->config_set (cfg_sr_max_item_count, max_item_count); } diff --git a/src/lay/lay/laySearchReplaceDialog.cc b/src/lay/lay/laySearchReplaceDialog.cc index dc856b88b..030b2b6a8 100644 --- a/src/lay/lay/laySearchReplaceDialog.cc +++ b/src/lay/lay/laySearchReplaceDialog.cc @@ -1125,9 +1125,8 @@ SearchReplaceDialog::configure (const std::string &name, const std::string &valu } else if (name == cfg_sr_window_dim) { - double wdim = m_window_dim; - tl::from_string (value, wdim); - if (fabs (wdim - m_window_dim) > 1e-6) { + lay::Margin wdim = lay::Margin::from_string (value); + if (wdim != m_window_dim) { m_window_dim = wdim; need_update = true; } @@ -1754,15 +1753,17 @@ SearchReplaceDialog::result_selection_changed () if (! dbox.empty ()) { + double window_dim = m_window_dim.get (dbox); + if (m_window == FitCell) { view ()->zoom_fit (); } else if (m_window == FitMarker) { - view ()->zoom_box (dbox.enlarged (db::DVector (m_window_dim, m_window_dim))); + view ()->zoom_box (dbox.enlarged (db::DVector (window_dim, window_dim))); } else if (m_window == Center) { view ()->pan_center (dbox.p1 () + (dbox.p2 () - dbox.p1 ()) * 0.5); } else if (m_window == CenterSize) { - double w = std::max (dbox.width (), m_window_dim); - double h = std::max (dbox.height (), m_window_dim); + double w = std::max (dbox.width (), window_dim); + double h = std::max (dbox.height (), window_dim); db::DPoint center (dbox.p1 () + (dbox.p2 () - dbox.p1 ()) * 0.5); db::DVector d (w * 0.5, h * 0.5); view ()->zoom_box (db::DBox (center - d, center + d)); diff --git a/src/lay/lay/laySearchReplaceDialog.h b/src/lay/lay/laySearchReplaceDialog.h index ed5f90183..1e942f2b5 100644 --- a/src/lay/lay/laySearchReplaceDialog.h +++ b/src/lay/lay/laySearchReplaceDialog.h @@ -27,6 +27,7 @@ #include "ui_SearchReplaceDialog.h" #include "layBrowser.h" +#include "layMargin.h" #include "rdb.h" #include "dbLayout.h" #include "dbShape.h" @@ -180,7 +181,7 @@ private: int m_current_mode; window_type m_window; - double m_window_dim; + lay::Margin m_window_dim; unsigned int m_max_item_count; std::vector mp_markers; diff --git a/src/laybasic/laybasic/layMargin.cc b/src/laybasic/laybasic/layMargin.cc new file mode 100644 index 000000000..f03b193d4 --- /dev/null +++ b/src/laybasic/laybasic/layMargin.cc @@ -0,0 +1,114 @@ + +/* + + KLayout Layout Viewer + Copyright (C) 2006-2023 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 + +*/ + + +#include "layMargin.h" + +#include + +namespace lay +{ + +static const double delta = 1e-10; + +Margin::Margin (double value, bool relative) + : m_relative_value (0.0), m_absolute_value (0.0), m_relative_mode (relative) +{ + if (relative) { + m_relative_value = value; + } else { + m_absolute_value = value; + } +} + +bool +Margin::operator== (const lay::Margin &other) const +{ + return m_relative_mode == other.m_relative_mode && + fabs (m_absolute_value - other.m_absolute_value) < delta && + fabs (m_relative_value - other.m_relative_value) < delta; +} + +std::string +Margin::to_string () const +{ + std::string res; + if (m_relative_mode) { + res = std::string ("*") + tl::to_string (m_relative_value); + if (fabs (m_absolute_value) > delta) { + res += " "; + res += tl::to_string (m_absolute_value); + } + } else { + res = tl::to_string (m_absolute_value); + if (fabs (m_relative_value) > delta) { + res += " *"; + res += tl::to_string (m_relative_value); + } + } + + return res; +} + +Margin +Margin::from_string (const std::string &s) +{ + Margin res; + + tl::Extractor ex (s.c_str ()); + if (ex.test ("*")) { + double v = 0.0; + ex.read (v); + res.set_relative_mode (true); + res.set_relative_value (v); + if (! ex.at_end ()) { + ex.read (v); + res.set_absolute_value (v); + } + } else { + double v = 0.0; + ex.read (v); + res.set_relative_mode (false); + res.set_absolute_value (v); + if (ex.test ("*")) { + ex.read (v); + res.set_relative_value (v); + } + } + + return res; +} + +double +Margin::get (double dim) const +{ + return m_relative_mode ? dim * m_relative_value : m_absolute_value; +} + +double +Margin::get (const db::DBox &box) const +{ + return get (std::max (box.width (), box.height ())); +} + +} + diff --git a/src/laybasic/laybasic/layMargin.h b/src/laybasic/laybasic/layMargin.h new file mode 100644 index 000000000..a971f0c47 --- /dev/null +++ b/src/laybasic/laybasic/layMargin.h @@ -0,0 +1,140 @@ + +/* + + KLayout Layout Viewer + Copyright (C) 2006-2023 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 + +*/ + + +#ifndef HDR_layMargin +#define HDR_layMargin + +#include "laybasicCommon.h" + +#include "dbBox.h" + +namespace lay +{ + +/** + * @brief A class represeting a margin on size + * + * Margin or size can be specified absolutely (in micron units) or relative + * to some object (given by a size or a box). + * + * The object keeps relative and absolute values so it can be easily + * switched. + */ + +class LAYBASIC_PUBLIC Margin +{ +public: + /** + * @brief The constructor + */ + Margin (double value = 0.0, bool relative = false); + + /** + * @brief Equality + */ + bool operator== (const lay::Margin &other) const; + + /** + * @brief Inequality + */ + bool operator!= (const lay::Margin &other) const + { + return ! operator== (other); + } + + /** + * @brief Gets the relative value + */ + double relative_value () const + { + return m_relative_value; + } + + /** + * @brief Sets the relative value + */ + void set_relative_value (double v) + { + m_relative_value = v; + } + + /** + * @brief Gets the absolute value + */ + double absolute_value () const + { + return m_absolute_value; + } + + /** + * @brief Sets the absolute value + */ + void set_absolute_value (double v) + { + m_absolute_value = v; + } + + /** + * @brief Gets a value indicating whether the relative value shall be used + */ + bool relative_mode () const + { + return m_relative_mode; + } + + /** + * @brief Sets a value indicating whether the relative value shall be used + */ + void set_relative_mode (bool mode) + { + m_relative_mode = mode; + } + + /** + * @brief Converts the object to a string + */ + std::string to_string () const; + + /** + * @brief Creates the object from a string + */ + static Margin from_string (const std::string &s); + + /** + * @brief Gets the resulting value for a given object dimension + */ + double get (double dim) const; + + /** + * @brief Gets the resulting value for a given box + */ + double get (const db::DBox &box) const; + +private: + double m_relative_value, m_absolute_value; + bool m_relative_mode; +}; + +} + +#endif diff --git a/src/laybasic/laybasic/laybasic.pro b/src/laybasic/laybasic/laybasic.pro index bcd01c6d1..4262ca687 100644 --- a/src/laybasic/laybasic/laybasic.pro +++ b/src/laybasic/laybasic/laybasic.pro @@ -36,6 +36,7 @@ SOURCES += \ gsiDeclLayRdbAdded.cc \ layAbstractMenu.cc \ layLayoutViewConfig.cc \ + layMargin.cc \ laybasicForceLink.cc \ layAnnotationShapes.cc \ layBitmap.cc \ @@ -86,6 +87,7 @@ SOURCES += \ layUtils.cc \ HEADERS += \ + layMargin.h \ laybasicConfig.h \ laybasicForceLink.h \ layAbstractMenu.h \ diff --git a/src/laybasic/unit_tests/layMarginTests.cc b/src/laybasic/unit_tests/layMarginTests.cc new file mode 100644 index 000000000..92693d493 --- /dev/null +++ b/src/laybasic/unit_tests/layMarginTests.cc @@ -0,0 +1,82 @@ + +/* + + KLayout Layout Viewer + Copyright (C) 2006-2023 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 + +*/ + +#include "layMargin.h" + +#include "tlUnitTest.h" + +TEST(1) +{ + lay::Margin m; + + EXPECT_EQ (m.relative_mode (), false); + EXPECT_EQ (m.to_string (), "0"); + EXPECT_EQ (m.get (1.0), 0.0); + EXPECT_EQ (lay::Margin::from_string (m.to_string ()).to_string (), m.to_string ()); + + m.set_relative_mode (true); + EXPECT_EQ (m.get (1.0), 0.0); + EXPECT_EQ (m.relative_mode (), true); + EXPECT_EQ (m.to_string (), "*0"); + EXPECT_EQ (lay::Margin::from_string (m.to_string ()).to_string (), m.to_string ()); + + m = lay::Margin (1.0); + EXPECT_EQ (m.get (2.0), 1.0); + EXPECT_EQ (m.relative_mode (), false); + EXPECT_EQ (m.absolute_value (), 1.0); + EXPECT_EQ (m.to_string (), "1"); + EXPECT_EQ (lay::Margin::from_string (m.to_string ()).to_string (), m.to_string ()); + + m.set_absolute_value (2.0); + EXPECT_EQ (m.get (1.0), 2.0); + EXPECT_EQ (m.absolute_value (), 2.0); + EXPECT_EQ (m.to_string (), "2"); + EXPECT_EQ (lay::Margin::from_string (m.to_string ()).to_string (), m.to_string ()); + + m = lay::Margin (1.5, true); + EXPECT_EQ (m.get (1.0), 1.5); + EXPECT_EQ (m.get (db::DBox (0.0, 0.0, 1.0, 0.5)), 1.5); + EXPECT_EQ (m.get (db::DBox (0.0, 0.0, 1.0, 2.0)), 3.0); + EXPECT_EQ (m.relative_mode (), true); + EXPECT_EQ (m.relative_value (), 1.5); + EXPECT_EQ (m.to_string (), "*1.5"); + EXPECT_EQ (lay::Margin::from_string (m.to_string ()).to_string (), m.to_string ()); + + m.set_absolute_value (2.5); + EXPECT_EQ (m.get (1.0), 1.5); + EXPECT_EQ (m.to_string (), "*1.5 2.5"); + EXPECT_EQ (lay::Margin::from_string (m.to_string ()).to_string (), m.to_string ()); + EXPECT_EQ (m.absolute_value (), 2.5); + + m.set_relative_value (2.0); + EXPECT_EQ (m.get (1.0), 2.0); + EXPECT_EQ (m.to_string (), "*2 2.5"); + EXPECT_EQ (lay::Margin::from_string (m.to_string ()).to_string (), m.to_string ()); + EXPECT_EQ (m.relative_value (), 2.0); + + m.set_relative_mode (false); + EXPECT_EQ (m.get (1.0), 2.5); + EXPECT_EQ (m.absolute_value (), 2.5); + EXPECT_EQ (m.to_string (), "2.5 *2"); + EXPECT_EQ (lay::Margin::from_string (m.to_string ()).to_string (), m.to_string ()); + EXPECT_EQ (m.relative_value (), 2.0); +} diff --git a/src/laybasic/unit_tests/unit_tests.pro b/src/laybasic/unit_tests/unit_tests.pro index face73fbb..d0132ce06 100644 --- a/src/laybasic/unit_tests/unit_tests.pro +++ b/src/laybasic/unit_tests/unit_tests.pro @@ -11,6 +11,7 @@ SOURCES = \ layBitmap.cc \ layBitmapsToImage.cc \ layLayerProperties.cc \ + layMarginTests.cc \ layParsedLayerSource.cc \ layRenderer.cc \ layAbstractMenuTests.cc \ diff --git a/src/layui/layui/BrowseInstancesConfigPage.ui b/src/layui/layui/BrowseInstancesConfigPage.ui index 56edd0638..3612a9411 100644 --- a/src/layui/layui/BrowseInstancesConfigPage.ui +++ b/src/layui/layui/BrowseInstancesConfigPage.ui @@ -1,53 +1,52 @@ - + + BrowseInstancesConfigPage - - + + 0 0 499 - 148 + 151 - - - 5 - 5 + + 0 0 - + Browse Cell Instances - - - 9 - - + + 6 + + 9 + - - + + Instance Browser Setup - - + + 9 - + 6 - + - + Qt::Horizontal - + QSizePolicy::Minimum - + 16 27 @@ -55,62 +54,62 @@ - - - + + + false - - - + + + Maximum number of instances to show - - + + - + Show in context of cell .. - + Show in context of any top cell - + Show in parent cell - - - + + + Context - - - + + + Window - + - + Qt::Horizontal - + QSizePolicy::Minimum - + 16 25 @@ -118,58 +117,55 @@ - - + + - + Don't change - + Fit whole context cell - + Fit marker with margin .. - + Center marker - + Center marker with size .. - - - - false - - + + - - - - - - - µm - - + + - + + + + lay::MarginWidget + QWidget +
layWidgets.h
+ 1 +
+
diff --git a/src/layui/layui/BrowseShapesConfigPage.ui b/src/layui/layui/BrowseShapesConfigPage.ui index f3a54544c..01cf9f264 100644 --- a/src/layui/layui/BrowseShapesConfigPage.ui +++ b/src/layui/layui/BrowseShapesConfigPage.ui @@ -1,7 +1,8 @@ - + + BrowseShapesConfigPage - - + + 0 0 @@ -9,61 +10,44 @@ 194 - + Browse Shapes - - - 9 - - + + 6 + + 9 + - - + + Shape Browser Setup - - + + 9 - + 6 - - - - µm - - - - - - + + + false - - - - false - - - - - - - + - + Qt::Horizontal - + QSizePolicy::Minimum - + 10 21 @@ -71,15 +55,15 @@ - + - + Qt::Horizontal - + QSizePolicy::Minimum - + 10 20 @@ -87,91 +71,105 @@ - - + + - + Show in context of cell .. - + Show in context of any top cell - + Show in context of local cell - - - - - - + + + Maximum number of shapes to show - - - + + + Context - - + + - + Don't change - + Fit context cell - + Fit marker with margin .. - + Center marker - + Center marker with size .. - - - + + + Maximum number of instances to show - - - + + + Window + + + + + + + + + - + + + + lay::MarginWidget + QWidget +
layWidgets.h
+ 1 +
+
diff --git a/src/layui/layui/MarkerBrowserConfigPage.ui b/src/layui/layui/MarkerBrowserConfigPage.ui index 7b05fea4e..227942cc4 100644 --- a/src/layui/layui/MarkerBrowserConfigPage.ui +++ b/src/layui/layui/MarkerBrowserConfigPage.ui @@ -17,7 +17,7 @@ 6 - + 9 @@ -26,14 +26,15 @@ Marker Browser - - 9 - 6 - - + + + + Maximum number of markers to show + + @@ -87,7 +88,7 @@ - + @@ -116,20 +117,6 @@ - - - - false - - - - - - - Maximum number of markers to show - - - @@ -137,12 +124,11 @@ - - - - µm - - + + + + +
@@ -150,6 +136,14 @@ + + + lay::MarginWidget + QWidget +
layWidgets.h
+ 1 +
+
diff --git a/src/layui/layui/layBrowseInstancesForm.cc b/src/layui/layui/layBrowseInstancesForm.cc index 8838f88ef..9caca2da6 100644 --- a/src/layui/layui/layBrowseInstancesForm.cc +++ b/src/layui/layui/layBrowseInstancesForm.cc @@ -200,9 +200,9 @@ BrowseInstancesConfigPage::setup (lay::Dispatcher *root) cbx_window->setCurrentIndex (int (wmode)); // window dimension - double wdim = 1.0; - root->config_get (cfg_cib_window_dim, wdim); - le_window->setText (tl::to_qstring (tl::to_string (wdim))); + std::string wdim_str; + root->config_get (cfg_cib_window_dim, wdim_str); + mrg_window->set_margin (lay::Margin::from_string (wdim_str)); // max. instance count unsigned int max_inst_count = 1000; @@ -223,22 +223,19 @@ BrowseInstancesConfigPage::context_changed (int m) void BrowseInstancesConfigPage::window_changed (int m) { - le_window->setEnabled (m == int (BrowseInstancesForm::FitMarker) || m == int (BrowseInstancesForm::CenterSize)); + mrg_window->setEnabled (m == int (BrowseInstancesForm::FitMarker) || m == int (BrowseInstancesForm::CenterSize)); } void BrowseInstancesConfigPage::commit (lay::Dispatcher *root) { - double dim = 1.0; - tl::from_string_ext (tl::to_string (le_window->text ()), dim); - unsigned int max_inst_count = 1000; tl::from_string_ext (tl::to_string (le_max_count->text ()), max_inst_count); root->config_set (cfg_cib_context_cell, tl::to_string (le_cell_name->text ())); root->config_set (cfg_cib_context_mode, BrowseInstancesForm::mode_type (cbx_context->currentIndex ()), BrowseInstancesContextModeConverter ()); root->config_set (cfg_cib_window_mode, BrowseInstancesForm::window_type (cbx_window->currentIndex ()), BrowseInstancesWindowModeConverter ()); - root->config_set (cfg_cib_window_dim, dim); + root->config_set (cfg_cib_window_dim, mrg_window->get_margin ().to_string ()); root->config_set (cfg_cib_max_inst_count, max_inst_count); } @@ -306,7 +303,7 @@ BrowseInstancesForm::BrowseInstancesForm (lay::Dispatcher *root, LayoutViewBase m_ef_enabled (true), m_mode (AnyTop), m_window (FitMarker), - m_window_dim (0.0), + m_window_dim (), m_max_inst_count (0), m_current_count (0) { @@ -390,9 +387,8 @@ BrowseInstancesForm::configure (const std::string &name, const std::string &valu } else if (name == cfg_cib_window_dim) { - double wdim = m_window_dim; - tl::from_string (value, wdim); - if (fabs (wdim - m_window_dim) > 1e-6) { + lay::Margin wdim = lay::Margin::from_string (value); + if (wdim != m_window_dim) { m_window_dim = wdim; need_update = true; } @@ -787,16 +783,18 @@ BrowseInstancesForm::highlight_current () if (index_set) { + double window_dim = m_window_dim.get (dbox); + view ()->select_cell (index, m_cv_index); if (m_window == FitCell) { view ()->zoom_fit (); } else if (m_window == FitMarker) { - view ()->zoom_box (dbox.enlarged (db::DVector (m_window_dim, m_window_dim))); + view ()->zoom_box (dbox.enlarged (db::DVector (window_dim, window_dim))); } else if (m_window == Center) { view ()->pan_center (dbox.p1 () + (dbox.p2 () - dbox.p1 ()) * 0.5); } else if (m_window == CenterSize) { - double w = std::max (dbox.width (), m_window_dim); - double h = std::max (dbox.height (), m_window_dim); + double w = std::max (dbox.width (), window_dim); + double h = std::max (dbox.height (), window_dim); db::DPoint center (dbox.p1 () + (dbox.p2 () - dbox.p1 ()) * 0.5); db::DVector d (w * 0.5, h * 0.5); view ()->zoom_box (db::DBox (center - d, center + d)); diff --git a/src/layui/layui/layBrowseInstancesForm.h b/src/layui/layui/layBrowseInstancesForm.h index e504cb56f..d31aa3e58 100644 --- a/src/layui/layui/layBrowseInstancesForm.h +++ b/src/layui/layui/layBrowseInstancesForm.h @@ -29,6 +29,7 @@ #include "ui_BrowseInstancesConfigPage.h" #include "layLayoutViewBase.h" +#include "layMargin.h" #include "layPluginConfigPage.h" #include "layBrowser.h" #include "layMarker.h" @@ -98,7 +99,7 @@ private: mode_type m_mode; window_type m_window; - double m_window_dim; + lay::Margin m_window_dim; std::string m_context_cell; unsigned int m_max_inst_count; diff --git a/src/layui/layui/layBrowseShapesForm.cc b/src/layui/layui/layBrowseShapesForm.cc index d3cbc4c75..8ceb2063a 100644 --- a/src/layui/layui/layBrowseShapesForm.cc +++ b/src/layui/layui/layBrowseShapesForm.cc @@ -202,9 +202,9 @@ BrowseShapesConfigPage::setup (lay::Dispatcher *root) cbx_window->setCurrentIndex (int (wmode)); // window dimension - double wdim = 1.0; - root->config_get (cfg_shb_window_dim, wdim); - le_window->setText (tl::to_qstring (tl::to_string (wdim))); + std::string wdim_str; + root->config_get (cfg_shb_window_dim, wdim_str); + mrg_window->set_margin (lay::Margin::from_string (wdim_str)); // max. instance count unsigned int max_inst_count = 1000; @@ -230,15 +230,12 @@ BrowseShapesConfigPage::context_changed (int m) void BrowseShapesConfigPage::window_changed (int m) { - le_window->setEnabled (m == int (BrowseShapesForm::FitMarker) || m == int (BrowseShapesForm::CenterSize)); + mrg_window->setEnabled (m == int (BrowseShapesForm::FitMarker) || m == int (BrowseShapesForm::CenterSize)); } void BrowseShapesConfigPage::commit (lay::Dispatcher *root) { - double dim = 1.0; - tl::from_string_ext (tl::to_string (le_window->text ()), dim); - unsigned int max_inst_count = 1000; tl::from_string_ext (tl::to_string (le_max_inst->text ()), max_inst_count); @@ -248,7 +245,7 @@ BrowseShapesConfigPage::commit (lay::Dispatcher *root) root->config_set (cfg_shb_context_cell, tl::to_string (le_cell_name->text ())); root->config_set (cfg_shb_context_mode, BrowseShapesForm::mode_type (cbx_context->currentIndex ()), BrowseShapesContextModeConverter ()); root->config_set (cfg_shb_window_mode, BrowseShapesForm::window_type (cbx_window->currentIndex ()), BrowseShapesWindowModeConverter ()); - root->config_set (cfg_shb_window_dim, dim); + root->config_set (cfg_shb_window_dim, mrg_window->get_margin ().to_string ()); root->config_set (cfg_shb_max_inst_count, max_inst_count); root->config_set (cfg_shb_max_shape_count, max_shape_count); } @@ -409,7 +406,7 @@ BrowseShapesForm::BrowseShapesForm (lay::Dispatcher *root, LayoutViewBase *vw) m_ef_enabled (true), m_mode (AnyTop), m_window (FitMarker), - m_window_dim (0.0), + m_window_dim (), m_max_inst_count (0), m_max_shape_count (0) { @@ -496,9 +493,8 @@ BrowseShapesForm::configure (const std::string &name, const std::string &value) } else if (name == cfg_shb_window_dim) { - double wdim = m_window_dim; - tl::from_string (value, wdim); - if (fabs (wdim - m_window_dim) > 1e-6) { + lay::Margin wdim = lay::Margin::from_string (value); + if (wdim != m_window_dim) { m_window_dim = wdim; need_update = true; } @@ -961,16 +957,18 @@ BrowseShapesForm::highlight_current () if (! dbox.empty ()) { + double window_dim = m_window_dim.get (dbox); + view ()->select_cell (cell_index, m_cv_index); if (m_window == FitCell) { view ()->zoom_fit (); } else if (m_window == FitMarker) { - view ()->zoom_box (dbox.enlarged (db::DVector (m_window_dim, m_window_dim))); + view ()->zoom_box (dbox.enlarged (db::DVector (window_dim, window_dim))); } else if (m_window == Center) { view ()->pan_center (dbox.p1 () + (dbox.p2 () - dbox.p1 ()) * 0.5); } else if (m_window == CenterSize) { - double w = std::max (dbox.width (), m_window_dim); - double h = std::max (dbox.height (), m_window_dim); + double w = std::max (dbox.width (), window_dim); + double h = std::max (dbox.height (), window_dim); db::DPoint center (dbox.p1 () + (dbox.p2 () - dbox.p1 ()) * 0.5); db::DVector d (w * 0.5, h * 0.5); view ()->zoom_box (db::DBox (center - d, center + d)); diff --git a/src/layui/layui/layBrowseShapesForm.h b/src/layui/layui/layBrowseShapesForm.h index b292bada2..8cbf89363 100644 --- a/src/layui/layui/layBrowseShapesForm.h +++ b/src/layui/layui/layBrowseShapesForm.h @@ -29,6 +29,7 @@ #include "ui_BrowseShapesConfigPage.h" #include "layLayoutViewBase.h" +#include "layMargin.h" #include "layPluginConfigPage.h" #include "layBrowser.h" #include "layMarker.h" @@ -99,7 +100,7 @@ private: mode_type m_mode; window_type m_window; - double m_window_dim; + lay::Margin m_window_dim; std::string m_context_cell; unsigned int m_max_inst_count; diff --git a/src/layui/layui/layWidgets.cc b/src/layui/layui/layWidgets.cc index fafdf6b53..ae9851843 100644 --- a/src/layui/layui/layWidgets.cc +++ b/src/layui/layui/layWidgets.cc @@ -1077,6 +1077,85 @@ ColorButton::browse_selected () } } +// ------------------------------------------------------------- +// MarginWidget implementation + +MarginWidget::MarginWidget (QWidget *parent, const char *name) + : QFrame (parent), m_margin () +{ + if (name) { + setObjectName (name); + } + + setFrameStyle (QFrame::NoFrame); + + QHBoxLayout *layout = new QHBoxLayout (this); + layout->setMargin (0); + + QLineEdit *le = new QLineEdit (this); + mp_abs_edit = le; + le->setSizePolicy (QSizePolicy (QSizePolicy::Fixed, QSizePolicy::Preferred)); + layout->addWidget (le); + + le = new QLineEdit (this); + mp_rel_edit = le; + le->setSizePolicy (QSizePolicy (QSizePolicy::Fixed, QSizePolicy::Preferred)); + layout->addWidget (le); + + QComboBox *mode = new QComboBox (this); + mode->addItem (tl::to_qstring ("µm")); + mode->addItem (tl::to_qstring ("%")); + mp_mode_cb = mode; + layout->addWidget (mode); + + connect (mode, SIGNAL (currentIndexChanged (int)), this, SLOT (mode_selection_changed ())); + + set_margin (lay::Margin ()); +} + +lay::Margin +MarginWidget::get_margin () const +{ + bool rel_mode = mp_mode_cb->currentIndex () == 1; + double rel = 0.0, abs = 0.0; + tl::from_string (tl::to_string (mp_rel_edit->text ()), rel); + tl::from_string (tl::to_string (mp_abs_edit->text ()), abs); + + lay::Margin m = m_margin; + m.set_relative_mode (rel_mode); + if (rel_mode) { + m.set_relative_value (rel * 0.01); + } else { + m.set_absolute_value (abs); + } + return m; +} + +void +MarginWidget::set_margin (const lay::Margin &margin) +{ + m_margin = margin; + + mp_abs_edit->setText (tl::to_qstring (tl::to_string (margin.absolute_value ()))); + mp_rel_edit->setText (tl::to_qstring (tl::to_string (margin.relative_value () * 100.0))); + mp_mode_cb->setCurrentIndex (margin.relative_mode () ? 1 : 0); + mode_selection_changed (); +} + +void +MarginWidget::mode_selection_changed () +{ + bool rel_mode = mp_mode_cb->currentIndex () == 1; + // NOTE: first hiding and then showing avoids layout flicker .. + mp_rel_edit->hide (); + mp_abs_edit->hide (); + if (rel_mode) { + mp_rel_edit->show (); + } else { + mp_abs_edit->show (); + } +} + // ------------------------------------------------------------- // DecoratedLineEdit implementation diff --git a/src/layui/layui/layWidgets.h b/src/layui/layui/layWidgets.h index 8fc1a8a1e..adfa708b6 100644 --- a/src/layui/layui/layWidgets.h +++ b/src/layui/layui/layWidgets.h @@ -26,6 +26,7 @@ #define HDR_layWidgets #include "layuiCommon.h" +#include "layMargin.h" #include "tlObject.h" #include "tlDeferredExecution.h" @@ -316,6 +317,33 @@ private slots: virtual void selected (); }; +/** + * @brief Margin edit box + * + * This class implements a special widget to edit a lay::Margin object. + * This object allows specification of a relative or absolute margin. + */ +class LAYUI_PUBLIC MarginWidget + : public QFrame +{ +Q_OBJECT + +public: + MarginWidget (QWidget *parent, const char *name = 0); + + lay::Margin get_margin () const; + void set_margin (const lay::Margin &margin); + +protected slots: + void mode_selection_changed (); + +private: + QLineEdit *mp_abs_edit; + QLineEdit *mp_rel_edit; + QComboBox *mp_mode_cb; + lay::Margin m_margin; +}; + /** * @brief Color chooser button * diff --git a/src/layui/layui/rdbMarkerBrowser.cc b/src/layui/layui/rdbMarkerBrowser.cc index e7bc8e8e3..95af622e7 100644 --- a/src/layui/layui/rdbMarkerBrowser.cc +++ b/src/layui/layui/rdbMarkerBrowser.cc @@ -28,6 +28,7 @@ #include "layConverters.h" #include "layDispatcher.h" #include "layUtils.h" +#include "layMargin.h" #include "ui_MarkerBrowserConfigPage.h" #include "ui_MarkerBrowserConfigPage2.h" @@ -159,9 +160,11 @@ MarkerBrowserConfigPage::setup (lay::Dispatcher *root) mp_ui->cbx_window->setCurrentIndex (int (wmode)); // window dimension - double wdim = 1.0; - root->config_get (cfg_rdb_window_dim, wdim); - mp_ui->le_window->setText (tl::to_qstring (tl::to_string (wdim))); + lay::Margin wdim (1.0); + std::string wdim_str = wdim.to_string (); + root->config_get (cfg_rdb_window_dim, wdim_str); + wdim = lay::Margin::from_string (wdim_str); + mp_ui->mgn_window->set_margin (wdim); // max. marker count unsigned int max_marker_count = 1000; @@ -175,21 +178,18 @@ MarkerBrowserConfigPage::setup (lay::Dispatcher *root) void MarkerBrowserConfigPage::window_changed (int m) { - mp_ui->le_window->setEnabled (m == int (rdb::FitMarker) || m == int (rdb::CenterSize)); + mp_ui->mgn_window->setEnabled (m == int (rdb::FitMarker) || m == int (rdb::CenterSize)); } void MarkerBrowserConfigPage::commit (lay::Dispatcher *root) { - double dim = 1.0; - tl::from_string_ext (tl::to_string (mp_ui->le_window->text ()), dim); - unsigned int max_markers_count = 1000; tl::from_string_ext (tl::to_string (mp_ui->le_max_markers->text ()), max_markers_count); root->config_set (cfg_rdb_context_mode, rdb::context_mode_type (mp_ui->cbx_context->currentIndex ()), MarkerBrowserContextModeConverter ()); root->config_set (cfg_rdb_window_mode, rdb::window_type (mp_ui->cbx_window->currentIndex ()), MarkerBrowserWindowModeConverter ()); - root->config_set (cfg_rdb_window_dim, dim); + root->config_set (cfg_rdb_window_dim, mp_ui->mgn_window->get_margin ().to_string ()); root->config_set (cfg_rdb_max_marker_count, max_markers_count); } diff --git a/src/layui/layui/rdbMarkerBrowserDialog.cc b/src/layui/layui/rdbMarkerBrowserDialog.cc index 6855ddd25..ed0dd5c45 100644 --- a/src/layui/layui/rdbMarkerBrowserDialog.cc +++ b/src/layui/layui/rdbMarkerBrowserDialog.cc @@ -470,9 +470,8 @@ MarkerBrowserDialog::configure (const std::string &name, const std::string &valu } else if (name == cfg_rdb_window_dim) { - double wdim = m_window_dim; - tl::from_string (value, wdim); - if (fabs (wdim - m_window_dim) > 1e-6) { + lay::Margin wdim = lay::Margin::from_string (value); + if (wdim != m_window_dim) { m_window_dim = wdim; need_update = true; } diff --git a/src/layui/layui/rdbMarkerBrowserDialog.h b/src/layui/layui/rdbMarkerBrowserDialog.h index 3991b6b65..56990e5e5 100644 --- a/src/layui/layui/rdbMarkerBrowserDialog.h +++ b/src/layui/layui/rdbMarkerBrowserDialog.h @@ -27,6 +27,7 @@ #include "layuiCommon.h" #include "layBrowser.h" +#include "layMargin.h" #include "tlColor.h" #include "rdbMarkerBrowser.h" @@ -78,7 +79,7 @@ private: Ui::MarkerBrowserDialog *mp_ui; context_mode_type m_context; window_type m_window; - double m_window_dim; + lay::Margin m_window_dim; unsigned int m_max_marker_count; tl::Color m_marker_color; int m_marker_line_width; diff --git a/src/layui/layui/rdbMarkerBrowserPage.cc b/src/layui/layui/rdbMarkerBrowserPage.cc index 822d19572..e9cab1a57 100644 --- a/src/layui/layui/rdbMarkerBrowserPage.cc +++ b/src/layui/layui/rdbMarkerBrowserPage.cc @@ -1838,7 +1838,7 @@ MarkerBrowserPage::marker_double_clicked (const QModelIndex &) } void -MarkerBrowserPage::set_window (rdb::window_type window, double window_dim, rdb::context_mode_type context) +MarkerBrowserPage::set_window (rdb::window_type window, const lay::Margin &window_dim, rdb::context_mode_type context) { if (window != m_window || window_dim != m_window_dim || context != m_context) { m_window = window; @@ -2280,15 +2280,17 @@ MarkerBrowserPage::do_update_markers () if (mp_view && ! m_markers_bbox.empty ()) { + double wdim = m_window_dim.get (m_markers_bbox); + if (m_window == FitCell) { mp_view->zoom_fit (); } else if (m_window == FitMarker) { - mp_view->zoom_box (m_markers_bbox.enlarged (db::DVector (m_window_dim, m_window_dim))); + mp_view->zoom_box (m_markers_bbox.enlarged (db::DVector (wdim, wdim))); } else if (m_window == Center) { mp_view->pan_center (m_markers_bbox.p1 () + (m_markers_bbox.p2 () - m_markers_bbox.p1 ()) * 0.5); } else if (m_window == CenterSize) { - double w = std::max (m_markers_bbox.width (), m_window_dim); - double h = std::max (m_markers_bbox.height (), m_window_dim); + double w = std::max (m_markers_bbox.width (), wdim); + double h = std::max (m_markers_bbox.height (), wdim); db::DPoint center (m_markers_bbox.p1 () + (m_markers_bbox.p2 () - m_markers_bbox.p1 ()) * 0.5); db::DVector d (w * 0.5, h * 0.5); mp_view->zoom_box (db::DBox (center - d, center + d)); diff --git a/src/layui/layui/rdbMarkerBrowserPage.h b/src/layui/layui/rdbMarkerBrowserPage.h index 68832f04c..d9c1cb080 100644 --- a/src/layui/layui/rdbMarkerBrowserPage.h +++ b/src/layui/layui/rdbMarkerBrowserPage.h @@ -27,6 +27,7 @@ #include "ui_MarkerBrowserPage.h" #include "rdbMarkerBrowser.h" +#include "layMargin.h" #include "tlDeferredExecution.h" #include "tlColor.h" #include "dbBox.h" @@ -137,7 +138,7 @@ public: /** * @brief Set the window type and window dimensions */ - void set_window (rdb::window_type window_type, double window_dim, rdb::context_mode_type context); + void set_window (rdb::window_type window_type, const lay::Margin &window_dim, rdb::context_mode_type context); /** * @brief Set the maximum number of markers shown in the marker selection list @@ -212,7 +213,7 @@ private: bool m_in_directory_selection_change; rdb::context_mode_type m_context; rdb::window_type m_window; - double m_window_dim; + lay::Margin m_window_dim; size_t m_max_marker_count; tl::Color m_marker_color; int m_marker_line_width;