Provide a solution of feature request #2024

- There is a new configuration page entry called
  "Min spacing" for the grid. The default value is 4.
  The value specifies the grid min spacing in
  units of UI font height.
- A bugfix is included: the ruler now is drawn after
  the grid, hence is not hidden by it (specifically
  in checkerboard pattern mode)
- To allow bigger grid spacing, the ruler now
  is allowed to grow bigger than before.
This commit is contained in:
Matthias Koefferlein 2025-04-26 16:52:39 +02:00
parent 449a9a968e
commit 2bd82af6fe
5 changed files with 271 additions and 208 deletions

View File

@ -43,6 +43,7 @@ static const std::string cfg_grid_grid_color ("grid-grid-color");
static const std::string cfg_grid_style0 ("grid-style0");
static const std::string cfg_grid_style1 ("grid-style1");
static const std::string cfg_grid_style2 ("grid-style2");
static const std::string cfg_grid_density ("grid-density");
static const std::string cfg_grid_visible ("grid-visible");
static const std::string cfg_grid_micron ("grid-micron");
static const std::string cfg_grid_show_ruler ("grid-show-ruler");

View File

@ -7,7 +7,7 @@
<x>0</x>
<y>0</y>
<width>483</width>
<height>341</height>
<height>361</height>
</rect>
</property>
<property name="windowTitle">
@ -59,6 +59,23 @@
<property name="spacing">
<number>6</number>
</property>
<item row="3" column="1">
<widget class="QLabel" name="label_2">
<property name="text">
<string>Far style</string>
</property>
<property name="alignment">
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
</property>
</widget>
</item>
<item row="10" column="2" colspan="2">
<widget class="QCheckBox" name="show_ruler">
<property name="text">
<string>Show ruler</string>
</property>
</widget>
</item>
<item row="2" column="2" colspan="2">
<widget class="QComboBox" name="style1_cbx">
<item>
@ -108,7 +125,122 @@
</item>
</widget>
</item>
<item row="10" column="1">
<item row="2" column="4">
<spacer>
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>40</width>
<height>20</height>
</size>
</property>
</spacer>
</item>
<item row="0" column="3">
<spacer>
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>40</width>
<height>20</height>
</size>
</property>
</spacer>
</item>
<item row="1" column="0" colspan="5">
<widget class="Line" name="line">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
</widget>
</item>
<item row="8" column="2">
<widget class="QPushButton" name="grid_axis_color_pb">
<property name="text">
<string/>
</property>
</widget>
</item>
<item row="2" column="0">
<widget class="QLabel" name="label_5">
<property name="text">
<string>Grid </string>
</property>
</widget>
</item>
<item row="6" column="0" colspan="5">
<widget class="Line" name="line_2">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
</widget>
</item>
<item row="0" column="2">
<widget class="QPushButton" name="grid_net_color_pb">
<property name="sizePolicy">
<sizepolicy hsizetype="Preferred" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="text">
<string/>
</property>
</widget>
</item>
<item row="10" column="0">
<widget class="QLabel" name="label_8">
<property name="text">
<string>Ruler</string>
</property>
</widget>
</item>
<item row="11" column="2">
<widget class="QPushButton" name="grid_ruler_color_pb">
<property name="text">
<string/>
</property>
</widget>
</item>
<item row="7" column="0">
<widget class="QLabel" name="label_9">
<property name="text">
<string>Axis</string>
</property>
</widget>
</item>
<item row="4" column="2">
<widget class="QPushButton" name="grid_grid_color_pb">
<property name="text">
<string/>
</property>
</widget>
</item>
<item row="2" column="1">
<widget class="QLabel" name="Close style">
<property name="text">
<string>Close style</string>
</property>
<property name="alignment">
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
</property>
</widget>
</item>
<item row="0" column="0" colspan="2">
<widget class="QLabel" name="label_3">
<property name="text">
<string>Color (all)</string>
</property>
<property name="alignment">
<set>Qt::AlignLeading|Qt::AlignLeft|Qt::AlignVCenter</set>
</property>
</widget>
</item>
<item row="11" column="1">
<widget class="QLabel" name="label_7">
<property name="text">
<string>Color</string>
@ -118,14 +250,17 @@
</property>
</widget>
</item>
<item row="5" column="0" colspan="5">
<widget class="Line" name="line_2">
<property name="orientation">
<enum>Qt::Horizontal</enum>
<item row="7" column="1">
<widget class="QLabel" name="label_4">
<property name="text">
<string>Style</string>
</property>
<property name="alignment">
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
</property>
</widget>
</item>
<item row="6" column="2" colspan="2">
<item row="7" column="2" colspan="2">
<widget class="QComboBox" name="style0_cbx">
<item>
<property name="text">
@ -169,30 +304,23 @@
</item>
</widget>
</item>
<item row="0" column="3">
<spacer>
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>40</width>
<height>20</height>
</size>
</property>
</spacer>
</item>
<item row="10" column="2">
<widget class="QPushButton" name="grid_ruler_color_pb">
<item row="8" column="1">
<widget class="QLabel" name="label_6">
<property name="text">
<string/>
<string>Color</string>
</property>
<property name="alignment">
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
</property>
</widget>
</item>
<item row="1" column="0" colspan="5">
<widget class="Line" name="line">
<property name="orientation">
<enum>Qt::Horizontal</enum>
<item row="4" column="1">
<widget class="QLabel" name="label">
<property name="text">
<string>Color</string>
</property>
<property name="alignment">
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
</property>
</widget>
</item>
@ -245,141 +373,37 @@
</item>
</widget>
</item>
<item row="3" column="1">
<widget class="QLabel" name="label_2">
<property name="text">
<string>Far style</string>
</property>
<property name="alignment">
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
</property>
</widget>
</item>
<item row="2" column="1">
<widget class="QLabel" name="Close style">
<property name="text">
<string>Close style</string>
</property>
<property name="alignment">
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
</property>
</widget>
</item>
<item row="0" column="0" colspan="2">
<widget class="QLabel" name="label_3">
<property name="text">
<string>Color (all)</string>
</property>
<property name="alignment">
<set>Qt::AlignLeading|Qt::AlignLeft|Qt::AlignVCenter</set>
</property>
</widget>
</item>
<item row="4" column="2">
<widget class="QPushButton" name="grid_grid_color_pb">
<property name="text">
<string/>
</property>
</widget>
</item>
<item row="2" column="0">
<widget class="QLabel" name="label_5">
<property name="text">
<string>Grid </string>
</property>
</widget>
</item>
<item row="9" column="2" colspan="2">
<widget class="QCheckBox" name="show_ruler">
<property name="text">
<string>Show Ruler</string>
</property>
</widget>
</item>
<item row="7" column="2">
<widget class="QPushButton" name="grid_axis_color_pb">
<property name="text">
<string/>
</property>
</widget>
</item>
<item row="2" column="4">
<spacer>
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>40</width>
<height>20</height>
</size>
</property>
</spacer>
</item>
<item row="6" column="1">
<widget class="QLabel" name="label_4">
<property name="text">
<string>Style</string>
</property>
<property name="alignment">
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
</property>
</widget>
</item>
<item row="7" column="1">
<widget class="QLabel" name="label_6">
<property name="text">
<string>Color</string>
</property>
<property name="alignment">
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
</property>
</widget>
</item>
<item row="0" column="2">
<widget class="QPushButton" name="grid_net_color_pb">
<property name="sizePolicy">
<sizepolicy hsizetype="Preferred" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="text">
<string/>
</property>
</widget>
</item>
<item row="6" column="0">
<widget class="QLabel" name="label_9">
<property name="text">
<string>Axis</string>
</property>
</widget>
</item>
<item row="4" column="1">
<widget class="QLabel" name="label">
<property name="text">
<string>Color</string>
</property>
<property name="alignment">
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
</property>
</widget>
</item>
<item row="9" column="0">
<widget class="QLabel" name="label_8">
<property name="text">
<string>Ruler</string>
</property>
</widget>
</item>
<item row="8" column="0" colspan="5">
<item row="9" column="0" colspan="5">
<widget class="Line" name="line_3">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
</widget>
</item>
<item row="5" column="2">
<widget class="QSpinBox" name="grid_density_sb">
<property name="minimum">
<number>1</number>
</property>
</widget>
</item>
<item row="5" column="1">
<widget class="QLabel" name="label_10">
<property name="text">
<string>Min. spacing</string>
</property>
<property name="alignment">
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
</property>
</widget>
</item>
<item row="5" column="3" colspan="2">
<widget class="QLabel" name="label_11">
<property name="text">
<string>(Font height units)</string>
</property>
</widget>
</item>
</layout>
</widget>
</item>

View File

@ -41,6 +41,8 @@ namespace lay
// ------------------------------------------------------------
// Helper functions to get and set the configuration
int default_density = 4;
static struct {
lay::GridNet::GridStyle style;
const char *string;
@ -79,6 +81,20 @@ GridNetStyleConverter::to_string (lay::GridNet::GridStyle style)
return "";
}
void
GridNetDensityConverter::from_string (const std::string &value, int &density)
{
density = default_density; // original default
tl::Extractor ex (value.c_str ());
ex.try_read (density);
}
std::string
GridNetDensityConverter::to_string (int density)
{
return tl::to_string (density);
}
// ------------------------------------------------------------
// Implementation of the GridNetPluginDeclaration
@ -92,6 +108,7 @@ GridNetPluginDeclaration::get_options (std::vector < std::pair<std::string, std:
options.push_back (std::pair<std::string, std::string> (cfg_grid_style0, GridNetStyleConverter ().to_string (lay::GridNet::Invisible)));
options.push_back (std::pair<std::string, std::string> (cfg_grid_style1, GridNetStyleConverter ().to_string (lay::GridNet::Dots)));
options.push_back (std::pair<std::string, std::string> (cfg_grid_style2, GridNetStyleConverter ().to_string (lay::GridNet::TenthDottedLines)));
options.push_back (std::pair<std::string, std::string> (cfg_grid_density, ""));
options.push_back (std::pair<std::string, std::string> (cfg_grid_visible, tl::to_string (true)));
options.push_back (std::pair<std::string, std::string> (cfg_grid_show_ruler, tl::to_string (true)));
// grid-micron is not configured here since some other entity is supposed to do this.
@ -122,7 +139,8 @@ GridNet::GridNet (LayoutViewBase *view)
lay::Plugin (view),
mp_view (view),
m_visible (false), m_show_ruler (true), m_grid (1.0),
m_style0 (Invisible), m_style1 (Invisible), m_style2 (Invisible)
m_style0 (Invisible), m_style1 (Invisible), m_style2 (Invisible),
m_density (default_density)
{
// .. nothing yet ..
}
@ -175,6 +193,12 @@ GridNet::configure (const std::string &name, const std::string &value)
GridNetStyleConverter ().from_string (value, style);
need_update = test_and_set (m_style2, style);
} else if (name == cfg_grid_density) {
int density = 0;
GridNetDensityConverter ().from_string (value, density);
need_update = test_and_set (m_density, density);
} else if (name == cfg_grid_show_ruler) {
bool sr = false;
@ -246,13 +270,14 @@ GridNet::render_bg (const lay::Viewport &vp, ViewObjectCanvas &canvas)
// fw is the basic unit of the ruler geometry
int fwr = lay::FixedFont::get_font (bmp_canvas->font_resolution ()).width ();
int threshold = std::min (1000, m_density * fwr);
double dgrid = trans.ctrans (m_grid);
GridStyle style = m_style1;
// compute major grid and switch to secondary style if necessary
int s = 0;
while (dgrid < fwr * 4) {
while (dgrid < threshold) {
if (s == 0) {
dgrid *= 2.0;
} else if (s == 1) {
@ -279,56 +304,6 @@ GridNet::render_bg (const lay::Viewport &vp, ViewObjectCanvas &canvas)
int nx = int (dbworld.width () / grid + eps) + 2;
int ny = int (dbworld.height () / grid + eps) + 2;
if (m_show_ruler && dgrid < vp.width () * 0.2) {
int rh = int (floor (0.5 + fwr * 0.8));
int xoffset = int (floor (0.5 + fwr * 2.5));
int yoffset = int (floor (0.5 + fwr * 2.5));
painter.fill_rect (db::Point (xoffset, vp.height () - yoffset - rh / 2),
db::Point (xoffset + int (floor (0.5 + dgrid)), vp.height () - yoffset + rh / 2),
ruler_color);
painter.draw_rect (db::Point (xoffset + int (floor (0.5 + dgrid)), vp.height () - yoffset - rh / 2),
db::Point (xoffset + int (floor (0.5 + 2 * dgrid)), vp.height () - yoffset + rh / 2),
ruler_color);
painter.draw_text (tl::sprintf ("%g \265m", grid * 2).c_str (),
db::Point (xoffset + int (floor (0.5 + trans.ctrans (2 * grid))), vp.height () - yoffset - rh / 2 - 2),
ruler_color, -1, 1);
if (mp_view->global_trans ().fp_trans () != db::DFTrans ()) {
// draw a small "F" indicating any global transformation
db::Point pts[] = {
db::Point (-4, -5),
db::Point (-4, 5),
db::Point (4, 5),
db::Point (4, 3),
db::Point (-2, 3),
db::Point (-2, 1),
db::Point (3, 1),
db::Point (3, -1),
db::Point (-2, -1),
db::Point (-2, -5),
db::Point (-4, -5)
};
db::Polygon poly;
poly.assign_hull (&pts[0], &pts[0] + (sizeof (pts) / sizeof (pts[0])));
poly.transform (db::FTrans (mp_view->global_trans ().fp_trans ()));
for (db::Polygon::polygon_edge_iterator e = poly.begin_edge (); !e.at_end (); ++e) {
db::Point p0 (xoffset + 2 * rh, vp.height () - yoffset - rh * 5);
db::Point p1 = p0 + db::Vector (int (floor (0.5 + (*e).p1 ().x () * 0.1 * rh * 4)), -int (floor (0.5 + (*e).p1 ().y () * 0.1 * rh * 4)));
db::Point p2 = p0 + db::Vector (int (floor (0.5 + (*e).p2 ().x () * 0.1 * rh * 4)), -int (floor (0.5 + (*e).p2 ().y () * 0.1 * rh * 4)));
painter.draw_line (p1, p2, ruler_color);
}
}
}
// draw grid
if (style == Dots || style == TenthDottedLines ||
style == DottedLines || style == LightDottedLines) {
@ -549,6 +524,56 @@ GridNet::render_bg (const lay::Viewport &vp, ViewObjectCanvas &canvas)
}
if (m_show_ruler && dgrid < vp.width () * 0.4) {
int rh = int (floor (0.5 + fwr * 0.8));
int xoffset = int (floor (0.5 + fwr * 2.5));
int yoffset = int (floor (0.5 + fwr * 2.5));
painter.fill_rect (db::Point (xoffset, vp.height () - yoffset - rh / 2),
db::Point (xoffset + int (floor (0.5 + dgrid)), vp.height () - yoffset + rh / 2),
ruler_color);
painter.draw_rect (db::Point (xoffset + int (floor (0.5 + dgrid)), vp.height () - yoffset - rh / 2),
db::Point (xoffset + int (floor (0.5 + 2 * dgrid)), vp.height () - yoffset + rh / 2),
ruler_color);
painter.draw_text (tl::sprintf ("%g \265m", grid * 2).c_str (),
db::Point (xoffset + int (floor (0.5 + trans.ctrans (2 * grid))), vp.height () - yoffset - rh / 2 - 2),
ruler_color, -1, 1);
if (mp_view->global_trans ().fp_trans () != db::DFTrans ()) {
// draw a small "F" indicating any global transformation
db::Point pts[] = {
db::Point (-4, -5),
db::Point (-4, 5),
db::Point (4, 5),
db::Point (4, 3),
db::Point (-2, 3),
db::Point (-2, 1),
db::Point (3, 1),
db::Point (3, -1),
db::Point (-2, -1),
db::Point (-2, -5),
db::Point (-4, -5)
};
db::Polygon poly;
poly.assign_hull (&pts[0], &pts[0] + (sizeof (pts) / sizeof (pts[0])));
poly.transform (db::FTrans (mp_view->global_trans ().fp_trans ()));
for (db::Polygon::polygon_edge_iterator e = poly.begin_edge (); !e.at_end (); ++e) {
db::Point p0 (xoffset + 2 * rh, vp.height () - yoffset - rh * 5);
db::Point p1 = p0 + db::Vector (int (floor (0.5 + (*e).p1 ().x () * 0.1 * rh * 4)), -int (floor (0.5 + (*e).p1 ().y () * 0.1 * rh * 4)));
db::Point p2 = p0 + db::Vector (int (floor (0.5 + (*e).p2 ().x () * 0.1 * rh * 4)), -int (floor (0.5 + (*e).p2 ().y () * 0.1 * rh * 4)));
painter.draw_line (p1, p2, ruler_color);
}
}
}
}
}

View File

@ -87,6 +87,7 @@ private:
GridStyle m_style0;
GridStyle m_style1;
GridStyle m_style2;
int m_density;
};
class GridNetStyleConverter
@ -96,6 +97,13 @@ public:
std::string to_string (lay::GridNet::GridStyle style);
};
class GridNetDensityConverter
{
public:
void from_string (const std::string &value, int &density);
std::string to_string (int density);
};
}
#endif

View File

@ -94,6 +94,10 @@ GridNetConfigPage::setup (lay::Dispatcher *root)
style = lay::GridNet::Invisible;
root->config_get (cfg_grid_style2, style, GridNetStyleConverter ());
mp_ui->style2_cbx->setCurrentIndex (int (style));
int density = 0;
root->config_get (cfg_grid_density, density, GridNetDensityConverter ());
mp_ui->grid_density_sb->setValue (density);
}
void
@ -108,6 +112,7 @@ GridNetConfigPage::commit (lay::Dispatcher *root)
root->config_set (cfg_grid_style0, lay::GridNet::GridStyle (mp_ui->style0_cbx->currentIndex ()), GridNetStyleConverter ());
root->config_set (cfg_grid_style1, lay::GridNet::GridStyle (mp_ui->style1_cbx->currentIndex ()), GridNetStyleConverter ());
root->config_set (cfg_grid_style2, lay::GridNet::GridStyle (mp_ui->style2_cbx->currentIndex ()), GridNetStyleConverter ());
root->config_set (cfg_grid_density, mp_ui->grid_density_sb->value (), GridNetDensityConverter ());
}
} // namespace lay