mirror of https://github.com/KLayout/klayout.git
First new implementation of "tap" and some enhancements/bugfixes/refactoring
- Layer icons can be obtained now - Icon dimension is arbitrary - Scaling icons for layer list - More robust event handling in case of pop-up menus (selector) - "Tap" will noe pop up a menu with all layers below the cursor. When selected, the current layer is switched.
This commit is contained in:
parent
f810eae7a0
commit
1887fd715a
|
|
@ -30,7 +30,11 @@
|
|||
#include "tlExceptions.h"
|
||||
#include "layLayoutView.h"
|
||||
#include "layDialogs.h"
|
||||
#include "laySelector.h"
|
||||
#include "layCellSelectionForm.h"
|
||||
#include "layFinder.h"
|
||||
#include "layLayerProperties.h"
|
||||
#include "layLayerTreeModel.h"
|
||||
#include "tlProgress.h"
|
||||
#include "edtPlugin.h"
|
||||
#include "edtMainService.h"
|
||||
|
|
@ -41,6 +45,8 @@
|
|||
#include "edtEditorOptionsPages.h"
|
||||
|
||||
#include <QMessageBox>
|
||||
#include <QFontInfo>
|
||||
#include <QWidgetAction>
|
||||
|
||||
namespace edt
|
||||
{
|
||||
|
|
@ -1941,21 +1947,60 @@ MainService::cm_make_array ()
|
|||
void
|
||||
MainService::cm_tap ()
|
||||
{
|
||||
tl_assert (view ()->is_editable ());
|
||||
check_no_guiding_shapes ();
|
||||
if (! view ()->view_object_widget ()->mouse_in_window ()) {
|
||||
return;
|
||||
}
|
||||
|
||||
std::vector<edt::Service *> edt_services = view ()->get_plugins <edt::Service> ();
|
||||
lay::ShapeFinder finder (true /*point mode*/, false /*all hierarchy levels*/, db::ShapeIterator::All, 0);
|
||||
|
||||
// get (common) cellview index of the selected shapes
|
||||
for (std::vector<edt::Service *>::const_iterator es = edt_services.begin (); es != edt_services.end (); ++es) {
|
||||
for (edt::Service::obj_iterator s = (*es)->selection ().begin (); s != (*es)->selection ().end (); ++s) {
|
||||
const lay::CellView &cv = view ()->cellview (s->cv_index ());
|
||||
if (cv.is_valid () && ! s->is_cell_inst ()) {
|
||||
view ()->set_current_layer (s->cv_index (), cv->layout ().get_properties (s->layer ()));
|
||||
return;
|
||||
}
|
||||
// capture all objects in point mode (default: capture one only)
|
||||
finder.set_catch_all (true);
|
||||
|
||||
// go through all visible layers of all cellviews
|
||||
db::DPoint pt = view ()->view_object_widget ()->mouse_position_um ();
|
||||
finder.find (view (), db::DBox (pt, pt));
|
||||
|
||||
std::set<std::pair<unsigned int, unsigned int> > layers_in_selection;
|
||||
|
||||
for (lay::ShapeFinder::iterator f = finder.begin (); f != finder.end (); ++f) {
|
||||
// ignore guiding shapes
|
||||
if (f->layer () != view ()->cellview (f->cv_index ())->layout ().guiding_shape_layer ()) {
|
||||
layers_in_selection.insert (std::make_pair (f->cv_index (), f->layer ()));
|
||||
}
|
||||
}
|
||||
|
||||
std::vector<lay::LayerPropertiesConstIterator> tapped_layers;
|
||||
for (lay::LayerPropertiesConstIterator lp = view ()->begin_layers (view ()->current_layer_list ()); ! lp.at_end (); ++lp) {
|
||||
const lay::LayerPropertiesNode *ln = lp.operator-> ();
|
||||
if (layers_in_selection.find (std::make_pair ((unsigned int) ln->cellview_index (), (unsigned int) ln->layer_index ())) != layers_in_selection.end ()) {
|
||||
tapped_layers.push_back (lp);
|
||||
}
|
||||
}
|
||||
|
||||
if (tapped_layers.empty ()) {
|
||||
return;
|
||||
}
|
||||
|
||||
// List the layers under the cursor as pop up a menu
|
||||
|
||||
std::auto_ptr<QMenu> menu (new QMenu (view ()));
|
||||
menu->show ();
|
||||
|
||||
int icon_size = menu->style ()->pixelMetric (QStyle::PM_ButtonIconSize);
|
||||
|
||||
QPoint mp = view ()->view_object_widget ()->mapToGlobal (view ()->view_object_widget ()->mouse_position ());
|
||||
|
||||
for (std::vector<lay::LayerPropertiesConstIterator>::const_iterator l = tapped_layers.begin (); l != tapped_layers.end (); ++l) {
|
||||
QAction *a = menu->addAction (lay::LayerTreeModel::icon_for_layer (*l, view (), icon_size, icon_size, 0, true), tl::to_qstring ((*l)->source (true).to_string ()));
|
||||
a->setData (int (l - tapped_layers.begin ()));
|
||||
}
|
||||
|
||||
QAction *action = menu->exec (mp);
|
||||
if (action) {
|
||||
int index = action->data ().toInt ();
|
||||
lay::LayerPropertiesConstIterator iter = tapped_layers [index];
|
||||
view ()->set_current_layer (iter);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
|
|
|
|||
|
|
@ -380,7 +380,38 @@ Bitmap::fill (unsigned int y, unsigned int x1, unsigned int x2)
|
|||
}
|
||||
}
|
||||
|
||||
struct PosCompareF
|
||||
void
|
||||
Bitmap::clear (unsigned int y, unsigned int x1, unsigned int x2)
|
||||
{
|
||||
unsigned int b1 = x1 / 32;
|
||||
|
||||
uint32_t *sl = scanline (y);
|
||||
sl += b1;
|
||||
|
||||
unsigned int b = x2 / 32 - b1;
|
||||
if (b == 0) {
|
||||
|
||||
*sl &= ~masks [x2 % 32] | masks [x1 % 32];
|
||||
|
||||
} else if (b > 0) {
|
||||
|
||||
*sl++ &= masks [x1 % 32];
|
||||
while (b > 1) {
|
||||
*sl++ = 0;
|
||||
b--;
|
||||
}
|
||||
|
||||
unsigned int m = masks [x2 % 32];
|
||||
// Hint: if x2==width and width%32==0, sl must not be accessed. This is guaranteed by
|
||||
// checking if m != 0.
|
||||
if (m) {
|
||||
*sl &= ~m;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
struct PosCompareF
|
||||
{
|
||||
bool operator() (const RenderEdge &a, const RenderEdge &b) const
|
||||
{
|
||||
|
|
|
|||
|
|
@ -246,6 +246,17 @@ public:
|
|||
*/
|
||||
void fill (unsigned int y, unsigned int x1, unsigned int x2);
|
||||
|
||||
/**
|
||||
* @brief Clears the given part of the scanline
|
||||
*
|
||||
* Same as fill(), but resets the bits.
|
||||
*
|
||||
* @param y The scanline
|
||||
* @param x1 The start coordinate
|
||||
* @param x2 The end coordinate
|
||||
*/
|
||||
void clear (unsigned int y, unsigned int x1, unsigned int x2);
|
||||
|
||||
/**
|
||||
* @brief Merges the "from" bitmap into this
|
||||
*
|
||||
|
|
|
|||
|
|
@ -62,7 +62,7 @@ static int inst_point_sel_tests = 10000;
|
|||
|
||||
Finder::Finder (bool point_mode, bool top_level_sel)
|
||||
: m_min_level (0), m_max_level (0),
|
||||
mp_layout (0), mp_view (0), m_cv_index (0), m_point_mode (point_mode), m_top_level_sel (top_level_sel)
|
||||
mp_layout (0), mp_view (0), m_cv_index (0), m_point_mode (point_mode), m_catch_all (false), m_top_level_sel (top_level_sel)
|
||||
{
|
||||
m_distance = std::numeric_limits<double>::max ();
|
||||
}
|
||||
|
|
@ -558,41 +558,32 @@ ShapeFinder::visit_cell (const db::Cell &cell, const db::Box &search_box, const
|
|||
|
||||
if (match) {
|
||||
|
||||
lay::ObjectInstPath found;
|
||||
found.set_cv_index (m_cv_index);
|
||||
found.set_topcell (m_topcell);
|
||||
found.assign_path (path ().begin (), path ().end ());
|
||||
found.set_layer (*l);
|
||||
found.set_shape (*shape);
|
||||
|
||||
if (mp_excludes) {
|
||||
|
||||
// with an exclude list first create the selection item so we can check
|
||||
// if it's part of the exclude set.
|
||||
|
||||
lay::ObjectInstPath found;
|
||||
found.set_cv_index (m_cv_index);
|
||||
found.set_topcell (m_topcell);
|
||||
found.assign_path (path ().begin (), path ().end ());
|
||||
found.set_layer (*l);
|
||||
found.set_shape (*shape);
|
||||
|
||||
// in point mode just store the found object that has the least "distance" and is
|
||||
// not in the exclude set
|
||||
if (mp_excludes->find (found) == mp_excludes->end () && closer (d)) {
|
||||
match = (mp_excludes->find (found) == mp_excludes->end ());
|
||||
|
||||
if (m_founds.empty ()) {
|
||||
m_founds.push_back (found);
|
||||
} else {
|
||||
m_founds.front () = found;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
} else if (closer (d)) {
|
||||
if (match && (catch_all () || closer (d))) {
|
||||
|
||||
// in point mode just store that found that has the least "distance"
|
||||
if (m_founds.empty ()) {
|
||||
m_founds.push_back (lay::ObjectInstPath ());
|
||||
if (m_founds.empty () || catch_all ()) {
|
||||
m_founds.push_back (found);
|
||||
}
|
||||
|
||||
m_founds.back ().set_cv_index (m_cv_index);
|
||||
m_founds.back ().set_topcell (m_topcell);
|
||||
m_founds.back ().assign_path (path ().begin (), path ().end ());
|
||||
m_founds.back ().set_layer (*l);
|
||||
m_founds.back ().set_shape (*shape);
|
||||
m_founds.back () = found;
|
||||
|
||||
}
|
||||
|
||||
|
|
@ -848,52 +839,38 @@ InstFinder::visit_cell (const db::Cell &cell, const db::Box &search_box, const d
|
|||
|
||||
if (match) {
|
||||
|
||||
lay::ObjectInstPath found;
|
||||
found.set_cv_index (m_cv_index);
|
||||
found.set_topcell (m_topcell);
|
||||
found.assign_path (path ().begin (), path ().end ());
|
||||
|
||||
// add the selected instance as the last element of the path
|
||||
db::InstElement el;
|
||||
el.inst_ptr = *inst;
|
||||
if (! m_full_arrays) {
|
||||
el.array_inst = p;
|
||||
}
|
||||
found.add_path (el);
|
||||
|
||||
if (mp_excludes) {
|
||||
|
||||
// with an exclude list first create the selection item so we can check
|
||||
// if it's part of the exclude set.
|
||||
|
||||
lay::ObjectInstPath found;
|
||||
found.set_cv_index (m_cv_index);
|
||||
found.set_topcell (m_topcell);
|
||||
found.assign_path (path ().begin (), path ().end ());
|
||||
|
||||
// add the selected instance as the last element of the path
|
||||
db::InstElement el;
|
||||
el.inst_ptr = *inst;
|
||||
if (! m_full_arrays) {
|
||||
el.array_inst = p;
|
||||
}
|
||||
found.add_path (el);
|
||||
|
||||
// in point mode just store the found object that has the least "distance" and is
|
||||
// not in the exclude set
|
||||
if (mp_excludes->find (found) == mp_excludes->end () && closer (d)) {
|
||||
if (m_founds.empty ()) {
|
||||
m_founds.push_back (found);
|
||||
} else {
|
||||
m_founds.front () = found;
|
||||
}
|
||||
}
|
||||
match = (mp_excludes->find (found) == mp_excludes->end ());
|
||||
|
||||
} else if (closer (d)) {
|
||||
}
|
||||
|
||||
if (match && (catch_all () || closer (d))) {
|
||||
|
||||
// in point mode just store that found that has the least "distance"
|
||||
if (m_founds.empty ()) {
|
||||
if (m_founds.empty () || catch_all ()) {
|
||||
m_founds.push_back (lay::ObjectInstPath ());
|
||||
}
|
||||
|
||||
m_founds.back ().set_cv_index (m_cv_index);
|
||||
m_founds.back ().set_topcell (m_topcell);
|
||||
m_founds.back ().assign_path (path ().begin (), path ().end ());
|
||||
|
||||
// add the selected instance as the last element of the path
|
||||
db::InstElement el;
|
||||
el.inst_ptr = *inst;
|
||||
if (! m_full_arrays) {
|
||||
el.array_inst = p;
|
||||
}
|
||||
m_founds.back ().add_path (el);
|
||||
m_founds.back () = found;
|
||||
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -58,13 +58,42 @@ public:
|
|||
*
|
||||
* The point_mode is true, if the finder is supposed to operate in "point mode".
|
||||
* In point mode, the center of the search region is the reference point. In
|
||||
* non-point mode, every relevant found inside the search region should be
|
||||
* recorded.
|
||||
* non-point mode, every relevant found inside the search region will be
|
||||
* recorded (also see point_mode method).
|
||||
* The base class implementation just stores this flag and provides a read
|
||||
* accessor with the point_mode () method.
|
||||
*/
|
||||
Finder (bool point_mode, bool top_level_sel);
|
||||
|
||||
/**
|
||||
* @brief Gets a flag indicating whether point mode is enabled
|
||||
* If point mode is enabled in the constructor, the first will check for objects overlapping the
|
||||
* point (rather than being inside the box) and by default select a single object only.
|
||||
* See also "set_catch_all".
|
||||
*/
|
||||
bool point_mode () const
|
||||
{
|
||||
return m_point_mode;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Gets a flag indicating the capture all founds even in point mode
|
||||
*/
|
||||
bool catch_all () const
|
||||
{
|
||||
return m_catch_all;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Sets a flag indicating the capture all founds even in point mode
|
||||
* By default, in point mode only the closest found is returned. To catch all
|
||||
* founds in point mode too, set this flag to true.
|
||||
*/
|
||||
void set_catch_all (bool f)
|
||||
{
|
||||
m_catch_all = f;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Destructor (just provided to please the compiler)
|
||||
*/
|
||||
|
|
@ -87,11 +116,6 @@ protected:
|
|||
return m_layers;
|
||||
}
|
||||
|
||||
bool point_mode () const
|
||||
{
|
||||
return m_point_mode;
|
||||
}
|
||||
|
||||
const std::vector<db::InstElement> &path () const
|
||||
{
|
||||
return m_path;
|
||||
|
|
@ -166,6 +190,7 @@ private:
|
|||
std::vector<int> m_layers;
|
||||
double m_distance;
|
||||
bool m_point_mode;
|
||||
bool m_catch_all;
|
||||
bool m_top_level_sel;
|
||||
db::box_convert <db::CellInst> m_box_convert;
|
||||
db::box_convert <db::Cell> m_cell_box_convert;
|
||||
|
|
|
|||
|
|
@ -60,36 +60,6 @@
|
|||
namespace lay
|
||||
{
|
||||
|
||||
// --------------------------------------------------------------------
|
||||
// LCPTreeItemDelegate declaration & implementation
|
||||
|
||||
/**
|
||||
* @brief A layer tree widget helper class
|
||||
*
|
||||
* A specialization of the ItemDelegate that bypasses the computation
|
||||
* of sizeHint and returns the pixmap's size directly for higher
|
||||
* performance.
|
||||
*/
|
||||
|
||||
class LCPItemDelegate : public QItemDelegate
|
||||
{
|
||||
public:
|
||||
LCPItemDelegate (QWidget *parent)
|
||||
: QItemDelegate (parent)
|
||||
{ }
|
||||
|
||||
private:
|
||||
virtual QSize
|
||||
sizeHint (const QStyleOptionViewItem &style, const QModelIndex &index) const
|
||||
{
|
||||
if (index.column () == 0) {
|
||||
return QSize (40, 16);
|
||||
} else {
|
||||
return QItemDelegate::sizeHint (style, index);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
// --------------------------------------------------------------------
|
||||
// LCPTreeWidget declaration & implementation
|
||||
|
||||
|
|
@ -98,7 +68,6 @@ LCPTreeWidget::LCPTreeWidget (QWidget *parent, lay::LayerTreeModel *model, const
|
|||
{
|
||||
setObjectName (QString::fromUtf8 (name));
|
||||
setModel (model);
|
||||
setItemDelegate (new LCPItemDelegate (this));
|
||||
#if QT_VERSION >= 0x040200
|
||||
setAllColumnsShowFocus (true);
|
||||
#endif
|
||||
|
|
@ -326,7 +295,10 @@ LayerControlPanel::LayerControlPanel (lay::LayoutView *view, db::Manager *manage
|
|||
|
||||
mp_model = new lay::LayerTreeModel (this, view);
|
||||
mp_layer_list = new LCPTreeWidget (this, mp_model, "layer_tree");
|
||||
mp_layer_list->setUniformRowHeights (true);
|
||||
mp_model->set_font (mp_layer_list->font ());
|
||||
mp_layer_list->setIconSize (mp_model->icon_size ());
|
||||
|
||||
/*
|
||||
* At least with Qt 4.2.x setting uniform row heights has a strange side effect:
|
||||
* If a range is selected and the first selection is scrolled out of view, the
|
||||
|
|
@ -343,7 +315,6 @@ LayerControlPanel::LayerControlPanel (lay::LayoutView *view, db::Manager *manage
|
|||
mp_layer_list->header ()->hide ();
|
||||
mp_layer_list->setSelectionMode (QTreeView::ExtendedSelection);
|
||||
mp_layer_list->setRootIsDecorated (false);
|
||||
mp_layer_list->setIconSize (QSize (32, 16));
|
||||
// Custom resize mode makes the columns as narrow as possible
|
||||
#if QT_VERSION >= 0x050000
|
||||
mp_layer_list->header ()->setSectionResizeMode (QHeaderView::ResizeToContents);
|
||||
|
|
|
|||
|
|
@ -32,6 +32,7 @@
|
|||
#include <QTreeView>
|
||||
#include <QModelIndex>
|
||||
#include <QString>
|
||||
#include <QFontInfo>
|
||||
|
||||
#include <string.h>
|
||||
|
||||
|
|
@ -558,6 +559,161 @@ LayerTreeModel::empty_within_view_predicate (const QModelIndex &index) const
|
|||
}
|
||||
}
|
||||
|
||||
LAYBASIC_PUBLIC
|
||||
QIcon
|
||||
LayerTreeModel::icon_for_layer (const lay::LayerPropertiesConstIterator &iter, lay::LayoutView *view, unsigned int w, unsigned int h, unsigned int di_off, bool no_state)
|
||||
{
|
||||
h = std::max ((unsigned int) 16, h);
|
||||
w = std::max ((unsigned int) 16, w);
|
||||
|
||||
lay::color_t def_color = 0x808080;
|
||||
lay::color_t fill_color = iter->has_fill_color (true) ? iter->eff_fill_color (true) : def_color;
|
||||
lay::color_t frame_color = iter->has_frame_color (true) ? iter->eff_frame_color (true) : def_color;
|
||||
|
||||
QImage image (w, h, QImage::Format_ARGB32);
|
||||
image.fill (view->background_color ().rgb ());
|
||||
|
||||
// upper scanline is a dummy one
|
||||
uint32_t *sl0 = (uint32_t *) image.scanLine (0);
|
||||
uint32_t transparent = QColor (Qt::transparent).rgba ();
|
||||
for (size_t i = 0; i < w; ++i) {
|
||||
*sl0++ = transparent;
|
||||
}
|
||||
|
||||
// TODO: adjust the resolution according to the oversampling mode
|
||||
lay::Bitmap fill (w, h, 1.0);
|
||||
lay::Bitmap frame (w, h, 1.0);
|
||||
lay::Bitmap text (w, h, 1.0);
|
||||
lay::Bitmap vertex (w, h, 1.0);
|
||||
|
||||
unsigned int wp = w - 1;
|
||||
|
||||
if (! no_state && ! iter->visible (true)) {
|
||||
|
||||
wp = w / 4;
|
||||
|
||||
// Show the arrow if it is invisible also locally.
|
||||
if (! iter->visible (false)) {
|
||||
|
||||
unsigned int aw = h / 4;
|
||||
unsigned int ap = w / 2 - 1;
|
||||
for (unsigned int i = 0; i <= aw; ++i) {
|
||||
text.fill (h / 2 - 1 - i, ap, ap + aw - i + 1);
|
||||
text.fill (h / 2 - 1 + i, ap, ap + aw - i + 1);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
if (! no_state && view->no_stipples ()) {
|
||||
// Show a partial stipple pattern only for "no stipple" mode
|
||||
for (unsigned int i = 1; i < h - 2; ++i) {
|
||||
fill.fill (i, w - 1 - w / 4, w);
|
||||
}
|
||||
} else {
|
||||
for (unsigned int i = 1; i < h - 2; ++i) {
|
||||
fill.fill (i, w - 1 - wp, w);
|
||||
}
|
||||
}
|
||||
|
||||
int lw = iter->width (true);
|
||||
if (lw < 0) {
|
||||
// default line width is 0 for parents and 1 for leafs
|
||||
lw = iter->has_children () ? 0 : 1;
|
||||
}
|
||||
|
||||
int p0 = lw / 2;
|
||||
p0 = std::max (0, std::min (int (w / 4 - 1), p0));
|
||||
|
||||
int p1 = (lw - 1) / 2;
|
||||
p1 = std::max (0, std::min (int (w / 4 - 1), p1));
|
||||
|
||||
int p0x = p0, p1x = p1;
|
||||
unsigned int ddx = 0;
|
||||
unsigned int ddy = h - 2 - p1 - p0;
|
||||
if (iter->xfill (true)) {
|
||||
ddx = wp - p0 - p1 - 1;
|
||||
}
|
||||
unsigned int d = ddx / 2;
|
||||
|
||||
frame.fill (p0, w - 1 - (wp - p1), w);
|
||||
frame.fill (h - 2 - p1, w - 1 - (wp - p1), w);
|
||||
|
||||
for (unsigned int i = p0; i < h - 2; ++i) {
|
||||
|
||||
frame.fill (i, w - 1 - p0, w - p0);
|
||||
frame.fill (i, w - 1 - (wp - p1), w - (wp - p1));
|
||||
frame.fill (i, w - 1 - p0x, w - p0x);
|
||||
frame.fill (i, w - 1 - (wp - p1x), w - (wp - p1x));
|
||||
|
||||
while (d < ddx) {
|
||||
d += ddy;
|
||||
frame.fill (i, w - 1 - p0x, w - p0x);
|
||||
frame.fill (i, w - 1 - (wp - p1x), w - (wp - p1x));
|
||||
++p0x;
|
||||
++p1x;
|
||||
}
|
||||
|
||||
if (d >= ddx) {
|
||||
d -= ddx;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
if (! no_state && ! iter->valid (true)) {
|
||||
|
||||
unsigned int bp = w - 1 - ((w * 7) / 8 - 1);
|
||||
unsigned int be = bp + h / 2;
|
||||
unsigned int bw = h / 4 - 1;
|
||||
unsigned int by = h / 2 - 1;
|
||||
|
||||
for (unsigned int i = 0; i < bw + 2; ++i) {
|
||||
fill.clear (by - i, bp - 1, be);
|
||||
fill.clear (by + i, bp - 1, be);
|
||||
}
|
||||
|
||||
for (unsigned int i = 0; i < bw; ++i) {
|
||||
text.fill (by - i, bp + bw - i - 1, bp + bw - i + 1);
|
||||
text.fill (by - i - 1, bp + bw - i - 1, bp + bw - i + 1);
|
||||
text.fill (by - i, bp + bw + i, bp + bw + i + 2);
|
||||
text.fill (by - i - 1, bp + bw + i, bp + bw + i + 2);
|
||||
text.fill (by + i, bp + bw - i - 1, bp + bw - i + 1);
|
||||
text.fill (by + i + 1, bp + bw - i - 1, bp + bw - i + 1);
|
||||
text.fill (by + i, bp + bw + i, bp + bw + i + 2);
|
||||
text.fill (by + i + 1, bp + bw + i, bp + bw + i + 2);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
vertex.fill (h / 2 - 1, w - 1 - wp / 2, w - wp / 2);
|
||||
|
||||
lay::ViewOp::Mode mode = lay::ViewOp::Copy;
|
||||
|
||||
// create fill
|
||||
single_bitmap_to_image (lay::ViewOp (fill_color, mode, 0, iter->eff_dither_pattern (true), di_off), fill, &image, view->dither_pattern (), view->line_styles (), w, h);
|
||||
// create frame
|
||||
if (lw == 0) {
|
||||
single_bitmap_to_image (lay::ViewOp (frame_color, mode, 0 /*solid line*/, 2 /*dotted*/, 0), frame, &image, view->dither_pattern (), view->line_styles (), w, h);
|
||||
} else {
|
||||
single_bitmap_to_image (lay::ViewOp (frame_color, mode, iter->eff_line_style (true), 0, 0, lay::ViewOp::Rect, lw), frame, &image, view->dither_pattern (), view->line_styles (), w, h);
|
||||
}
|
||||
// create text
|
||||
single_bitmap_to_image (lay::ViewOp (frame_color, mode, 0, 0, 0), text, &image, view->dither_pattern (), view->line_styles (), w, h);
|
||||
// create vertex
|
||||
single_bitmap_to_image (lay::ViewOp (frame_color, mode, 0, 0, 0, lay::ViewOp::Cross, iter->marked (true) ? 9/*mark size*/ : 0), vertex, &image, view->dither_pattern (), view->line_styles (), w, h);
|
||||
|
||||
QPixmap pixmap = QPixmap::fromImage (image); // Qt 4.6.0 workaround
|
||||
return QIcon (pixmap);
|
||||
}
|
||||
|
||||
QSize
|
||||
LayerTreeModel::icon_size () const
|
||||
{
|
||||
unsigned int is = ((QFontInfo (m_font).pixelSize () + 15) / 16) * 16;
|
||||
return QSize (is * 2, is);
|
||||
}
|
||||
|
||||
QVariant
|
||||
LayerTreeModel::data (const QModelIndex &index, int role) const
|
||||
{
|
||||
|
|
@ -568,6 +724,16 @@ LayerTreeModel::data (const QModelIndex &index, int role) const
|
|||
|
||||
return QVariant ();
|
||||
|
||||
} else if (role == Qt::SizeHintRole) {
|
||||
|
||||
if (index.column () == 0) {
|
||||
// NOTE: for some reason, the widget clips the icon when inside a tree and needs a some what bigger width ..
|
||||
QSize is = icon_size ();
|
||||
return QVariant (is + QSize (is.width () / 4, 0));
|
||||
} else {
|
||||
return QVariant ();
|
||||
}
|
||||
|
||||
} else if (role == Qt::DisplayRole || role == Qt::EditRole) {
|
||||
|
||||
if (index.column () == 1) {
|
||||
|
|
@ -593,142 +759,10 @@ LayerTreeModel::data (const QModelIndex &index, int role) const
|
|||
}
|
||||
}
|
||||
|
||||
unsigned int w = 32;
|
||||
unsigned int h = 16;
|
||||
|
||||
QSize is = icon_size ();
|
||||
|
||||
if (animate_visible) {
|
||||
|
||||
lay::color_t def_color = 0x808080;
|
||||
lay::color_t fill_color = iter->has_fill_color (true) ? iter->eff_fill_color (true) : def_color;
|
||||
lay::color_t frame_color = iter->has_frame_color (true) ? iter->eff_frame_color (true) : def_color;
|
||||
|
||||
QImage image (w, h, QImage::Format_RGB32);
|
||||
image.fill (m_background_color.rgb ());
|
||||
|
||||
// TODO: adjust the resolution according to the oversampling mode
|
||||
lay::Bitmap fill (w, h, 1.0);
|
||||
lay::Bitmap frame (w, h, 1.0);
|
||||
lay::Bitmap text (w, h, 1.0);
|
||||
lay::Bitmap vertex (w, h, 1.0);
|
||||
|
||||
unsigned int mask_w = 31;
|
||||
unsigned int mask_all = 0xfffffffe;
|
||||
unsigned int mask_left = 0x80000000;
|
||||
unsigned int mask_right = 0x00000002;
|
||||
unsigned int mask_center = 0x00010000;
|
||||
|
||||
if (! iter->visible (true)) {
|
||||
|
||||
mask_w = 8;
|
||||
mask_all = 0xff800000;
|
||||
mask_left = 0x80000000;
|
||||
mask_right = 0x00800000;
|
||||
mask_center = 0x08000000;
|
||||
|
||||
// Show the arrow if it is invisible also locally.
|
||||
if (! iter->visible (false)) {
|
||||
text.scanline (4) [0] = 0x00008000 << 1;
|
||||
text.scanline (5) [0] = 0x00018000 << 1;
|
||||
text.scanline (6) [0] = 0x00038000 << 1;
|
||||
text.scanline (7) [0] = 0x00078000 << 1;
|
||||
text.scanline (8) [0] = 0x00038000 << 1;
|
||||
text.scanline (9) [0] = 0x00018000 << 1;
|
||||
text.scanline (10) [0] = 0x00008000 << 1;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
if (mp_view->no_stipples ()) {
|
||||
// Show a partial stipple pattern only for "no stipple" mode
|
||||
for (unsigned int i = 1; i < h - 2; ++i) {
|
||||
fill.scanline (i) [0] = 0xff800000;
|
||||
}
|
||||
} else {
|
||||
for (unsigned int i = 1; i < h - 2; ++i) {
|
||||
fill.scanline (i) [0] = mask_all;
|
||||
}
|
||||
}
|
||||
|
||||
int lw = iter->width (true);
|
||||
if (lw < 0) {
|
||||
// default line width is 0 for parents and 1 for leafs
|
||||
lw = iter->has_children () ? 0 : 1;
|
||||
}
|
||||
|
||||
int p0 = lw / 2;
|
||||
int p1 = (lw - 1) / 2;
|
||||
if (p0 < 0) {
|
||||
p0 = 0;
|
||||
} else if (p0 > 7) {
|
||||
p0 = 7;
|
||||
}
|
||||
if (p1 < 0) {
|
||||
p1 = 0;
|
||||
} else if (p1 > 7) {
|
||||
p1 = 7;
|
||||
}
|
||||
|
||||
int p0x = p0, p1x = p1;
|
||||
unsigned int ddx = 0;
|
||||
unsigned int ddy = h - 2 - p1 - p0;
|
||||
if (iter->xfill (true)) {
|
||||
ddx = mask_w - p0 - p1 - 1;
|
||||
}
|
||||
unsigned int d = ddx / 2;
|
||||
|
||||
frame.scanline (p0) [0] = mask_all << p1;
|
||||
for (unsigned int i = p0; i < h - 2; ++i) {
|
||||
frame.scanline (i) [0] |= (mask_left >> p0) | (mask_right << p1);
|
||||
frame.scanline (i) [0] |= (mask_left >> p0x) | (mask_right << p1x);
|
||||
while (d < ddx) {
|
||||
d += ddy;
|
||||
frame.scanline (i) [0] |= (mask_left >> p0x) | (mask_right << p1x);
|
||||
++p0x;
|
||||
++p1x;
|
||||
}
|
||||
if (d >= ddx) {
|
||||
d -= ddx;
|
||||
}
|
||||
}
|
||||
frame.scanline (h - 2 - p1) [0] = mask_all << p1;
|
||||
|
||||
if (! iter->valid (true)) {
|
||||
|
||||
text.scanline (4) [0] |= 0x00000c60;
|
||||
text.scanline (5) [0] |= 0x00000ee0;
|
||||
text.scanline (6) [0] |= 0x000007c0;
|
||||
text.scanline (7) [0] |= 0x00000380;
|
||||
text.scanline (8) [0] |= 0x000007c0;
|
||||
text.scanline (9) [0] |= 0x00000ee0;
|
||||
text.scanline (10) [0] |= 0x00000c60;
|
||||
|
||||
for (unsigned int i = 3; i < 12; ++i) {
|
||||
fill.scanline (i) [0] &= ~0x00001ff0;
|
||||
frame.scanline (i) [0] &= ~0x00001ff0;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
vertex.scanline (h / 2 - 1) [0] = mask_center;
|
||||
|
||||
lay::ViewOp::Mode mode = lay::ViewOp::Copy;
|
||||
|
||||
// create fill
|
||||
single_bitmap_to_image (lay::ViewOp (fill_color, mode, 0, iter->eff_dither_pattern (true), di_off), fill, &image, mp_view->dither_pattern (), mp_view->line_styles (), w, h);
|
||||
// create frame
|
||||
if (lw == 0) {
|
||||
single_bitmap_to_image (lay::ViewOp (frame_color, mode, 0 /*solid line*/, 2 /*dotted*/, 0), frame, &image, mp_view->dither_pattern (), mp_view->line_styles (), w, h);
|
||||
} else {
|
||||
single_bitmap_to_image (lay::ViewOp (frame_color, mode, iter->eff_line_style (true), 0, 0, lay::ViewOp::Rect, lw), frame, &image, mp_view->dither_pattern (), mp_view->line_styles (), w, h);
|
||||
}
|
||||
// create text
|
||||
single_bitmap_to_image (lay::ViewOp (frame_color, mode, 0, 0, 0), text, &image, mp_view->dither_pattern (), mp_view->line_styles (), w, h);
|
||||
// create vertex
|
||||
single_bitmap_to_image (lay::ViewOp (frame_color, mode, 0, 0, 0, lay::ViewOp::Cross, iter->marked (true) ? 9/*mark size*/ : 0), vertex, &image, mp_view->dither_pattern (),mp_view->line_styles (), w, h);
|
||||
|
||||
QPixmap pixmap = QPixmap::fromImage (image); // Qt 4.6.0 workaround
|
||||
return QVariant (QIcon (pixmap));
|
||||
|
||||
return QVariant (icon_for_layer (iter, mp_view, is.width (), is.height (), di_off));
|
||||
} else {
|
||||
return QVariant (QIcon ());
|
||||
}
|
||||
|
|
|
|||
|
|
@ -104,6 +104,16 @@ public:
|
|||
virtual QModelIndex index (int row, int column, const QModelIndex &parent) const;
|
||||
virtual QModelIndex parent (const QModelIndex &index) const;
|
||||
|
||||
/**
|
||||
* @brief Provides an icon for a given layer style
|
||||
*/
|
||||
static QIcon icon_for_layer (const lay::LayerPropertiesConstIterator &iter, lay::LayoutView *view, unsigned int w, unsigned int h, unsigned int di_offset, bool no_state = false);
|
||||
|
||||
/**
|
||||
* @brief Gets the preferred icon size
|
||||
*/
|
||||
QSize icon_size () const;
|
||||
|
||||
/**
|
||||
* @brief Convert a lay::LayerPropertiesConstIterator to a QModelIndex
|
||||
*/
|
||||
|
|
|
|||
|
|
@ -74,10 +74,7 @@ void
|
|||
SelectionService::deactivated ()
|
||||
{
|
||||
mp_view->clear_transient_selection ();
|
||||
if (mp_box) {
|
||||
delete mp_box;
|
||||
mp_box = 0;
|
||||
}
|
||||
reset_box ();
|
||||
}
|
||||
|
||||
void
|
||||
|
|
@ -102,7 +99,20 @@ SelectionService::timeout ()
|
|||
mp_view->transient_select (m_hover_point);
|
||||
}
|
||||
|
||||
bool
|
||||
void
|
||||
SelectionService::reset_box ()
|
||||
{
|
||||
if (mp_box) {
|
||||
|
||||
widget ()->ungrab_mouse (this);
|
||||
|
||||
delete mp_box;
|
||||
mp_box = 0;
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
bool
|
||||
SelectionService::wheel_event (int /*delta*/, bool /*horizonal*/, const db::DPoint & /*p*/, unsigned int /*buttons*/, bool /*prio*/)
|
||||
{
|
||||
return false;
|
||||
|
|
@ -115,19 +125,31 @@ SelectionService::enter_event (bool /*prio*/)
|
|||
return false;
|
||||
}
|
||||
|
||||
bool
|
||||
SelectionService::leave_event (bool /*prio*/)
|
||||
bool
|
||||
SelectionService::leave_event (bool prio)
|
||||
{
|
||||
m_mouse_in_window = false;
|
||||
|
||||
hover_reset ();
|
||||
|
||||
if (prio) {
|
||||
reset_box ();
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
bool
|
||||
SelectionService::mouse_move_event (const db::DPoint &p, unsigned int /*buttons*/, bool prio)
|
||||
SelectionService::mouse_move_event (const db::DPoint &p, unsigned int buttons, bool prio)
|
||||
{
|
||||
if (prio) {
|
||||
|
||||
m_current_position = p;
|
||||
|
||||
if ((buttons & LeftButton) == 0) {
|
||||
reset_box ();
|
||||
}
|
||||
|
||||
if (mp_box) {
|
||||
m_p2 = p;
|
||||
mp_box->set_points (m_p1, m_p2);
|
||||
|
|
@ -138,6 +160,7 @@ SelectionService::mouse_move_event (const db::DPoint &p, unsigned int /*buttons*
|
|||
}
|
||||
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
|
|
@ -145,6 +168,11 @@ bool
|
|||
SelectionService::mouse_double_click_event (const db::DPoint & /*p*/, unsigned int buttons, bool prio)
|
||||
{
|
||||
hover_reset ();
|
||||
|
||||
if (prio) {
|
||||
reset_box ();
|
||||
}
|
||||
|
||||
if (prio && (buttons & lay::LeftButton) != 0) {
|
||||
mp_view->show_properties (QApplication::activeWindow ());
|
||||
return true;
|
||||
|
|
@ -157,11 +185,18 @@ bool
|
|||
SelectionService::mouse_press_event (const db::DPoint &p, unsigned int buttons, bool prio)
|
||||
{
|
||||
hover_reset ();
|
||||
if (prio && ! mp_box && (buttons & lay::LeftButton) != 0) {
|
||||
mp_view->stop_redraw (); // TODO: how to restart if selection is aborted?
|
||||
m_buttons = buttons;
|
||||
begin (p);
|
||||
return true;
|
||||
|
||||
if (prio) {
|
||||
|
||||
reset_box ();
|
||||
|
||||
if ((buttons & lay::LeftButton) != 0) {
|
||||
mp_view->stop_redraw (); // TODO: how to restart if selection is aborted?
|
||||
m_buttons = buttons;
|
||||
begin (p);
|
||||
return true;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
return false;
|
||||
|
|
@ -170,7 +205,11 @@ SelectionService::mouse_press_event (const db::DPoint &p, unsigned int buttons,
|
|||
bool
|
||||
SelectionService::mouse_click_event (const db::DPoint &p, unsigned int buttons, bool prio)
|
||||
{
|
||||
if (prio && mp_view && widget ()->mouse_event_viewport ().contains (p) && (buttons & lay::LeftButton) != 0) {
|
||||
if (prio) {
|
||||
reset_box ();
|
||||
}
|
||||
|
||||
if (prio && mp_view && widget ()->mouse_event_viewport ().contains (p) && (buttons & lay::LeftButton) != 0) {
|
||||
|
||||
lay::Editable::SelectionMode mode = lay::Editable::Replace;
|
||||
bool shift = ((buttons & lay::ShiftButton) != 0);
|
||||
|
|
@ -211,12 +250,10 @@ bool
|
|||
SelectionService::mouse_release_event (const db::DPoint & /*p*/, unsigned int /*buttons*/, bool prio)
|
||||
{
|
||||
hover_reset ();
|
||||
|
||||
if (prio && mp_box) {
|
||||
|
||||
widget ()->ungrab_mouse (this);
|
||||
|
||||
delete mp_box;
|
||||
mp_box = 0;
|
||||
reset_box ();
|
||||
|
||||
if (mp_view) {
|
||||
|
||||
|
|
|
|||
|
|
@ -25,6 +25,8 @@
|
|||
#ifndef HDR_laySelector
|
||||
#define HDR_laySelector
|
||||
|
||||
#include "laybasicCommon.h"
|
||||
|
||||
#include "layViewObject.h"
|
||||
#include "layEditable.h"
|
||||
|
||||
|
|
@ -37,7 +39,7 @@ class RubberBox;
|
|||
class LayoutView;
|
||||
class LayoutCanvas;
|
||||
|
||||
class SelectionService
|
||||
class LAYBASIC_PUBLIC SelectionService
|
||||
: public QObject,
|
||||
public lay::ViewService
|
||||
{
|
||||
|
|
@ -77,6 +79,7 @@ private:
|
|||
virtual void deactivated ();
|
||||
|
||||
db::DPoint m_p1, m_p2;
|
||||
db::DPoint m_current_position;
|
||||
lay::LayoutView *mp_view;
|
||||
lay::RubberBox *mp_box;
|
||||
unsigned int m_color;
|
||||
|
|
@ -86,6 +89,8 @@ private:
|
|||
bool m_hover_wait;
|
||||
db::DPoint m_hover_point;
|
||||
bool m_mouse_in_window;
|
||||
|
||||
void reset_box ();
|
||||
};
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -272,6 +272,7 @@ ViewObjectWidget::ViewObjectWidget (QWidget *parent, const char *name)
|
|||
m_mouse_pressed_state (false),
|
||||
m_mouse_buttons (0),
|
||||
m_in_mouse_move (false),
|
||||
m_mouse_inside (false),
|
||||
m_cursor (lay::Cursor::none),
|
||||
m_default_cursor (lay::Cursor::none)
|
||||
{
|
||||
|
|
@ -363,6 +364,14 @@ ViewObjectWidget::set_default_cursor (lay::Cursor::cursor_shape cursor)
|
|||
}
|
||||
}
|
||||
|
||||
void
|
||||
ViewObjectWidget::ensure_entered ()
|
||||
{
|
||||
if (! m_mouse_inside) {
|
||||
enterEvent (0);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
ViewObjectWidget::begin_mouse_event (lay::Cursor::cursor_shape cursor)
|
||||
{
|
||||
|
|
@ -434,7 +443,7 @@ BEGIN_PROTECTED
|
|||
const DragDropDataBase *dd = get_drag_drop_data (event->mimeData ());
|
||||
if (dd) {
|
||||
|
||||
db::DPoint p = m_trans.inverted () * db::DPoint (event->pos ().x (), height () - 1 - event->pos ().y ());
|
||||
db::DPoint p = pixel_to_um (event->pos ());
|
||||
|
||||
bool done = drag_enter_event (p, dd);
|
||||
service_iterator svc = begin_services ();
|
||||
|
|
@ -479,7 +488,7 @@ BEGIN_PROTECTED
|
|||
const DragDropDataBase *dd = get_drag_drop_data (event->mimeData ());
|
||||
if (dd) {
|
||||
|
||||
db::DPoint p = m_trans.inverted () * db::DPoint (event->pos ().x (), height () - 1 - event->pos ().y ());
|
||||
db::DPoint p = pixel_to_um (event->pos ());
|
||||
|
||||
bool done = drag_move_event (p, dd);
|
||||
service_iterator svc = begin_services ();
|
||||
|
|
@ -503,7 +512,7 @@ BEGIN_PROTECTED
|
|||
const DragDropDataBase *dd = get_drag_drop_data (event->mimeData ());
|
||||
if (dd) {
|
||||
|
||||
db::DPoint p = m_trans.inverted () * db::DPoint (event->pos ().x (), height () - 1 - event->pos ().y ());
|
||||
db::DPoint p = pixel_to_um (event->pos ());
|
||||
|
||||
bool done = drop_event (p, dd);
|
||||
service_iterator svc = begin_services ();
|
||||
|
|
@ -523,6 +532,7 @@ void
|
|||
ViewObjectWidget::mouseMoveEvent (QMouseEvent *e)
|
||||
{
|
||||
BEGIN_PROTECTED
|
||||
ensure_entered ();
|
||||
m_mouse_pos = e->pos ();
|
||||
m_mouse_buttons = qt_to_buttons (e->buttons (), e->modifiers ());
|
||||
do_mouse_move ();
|
||||
|
|
@ -543,7 +553,7 @@ ViewObjectWidget::do_mouse_move ()
|
|||
|
||||
bool done = false;
|
||||
|
||||
db::DPoint p = m_trans.inverted () * db::DPoint (m_mouse_pressed.x (), height () - 1 - m_mouse_pressed.y ());
|
||||
db::DPoint p = pixel_to_um (m_mouse_pressed);
|
||||
|
||||
for (std::list<ViewService *>::iterator g = m_grabbed.begin (); !done && g != m_grabbed.end (); ) {
|
||||
std::list<ViewService *>::iterator gg = g;
|
||||
|
|
@ -578,7 +588,7 @@ ViewObjectWidget::do_mouse_move ()
|
|||
|
||||
bool done = false;
|
||||
|
||||
db::DPoint p = m_trans.inverted () * db::DPoint (m_mouse_pos.x (), height () - 1 - m_mouse_pos.y ());
|
||||
db::DPoint p = pixel_to_um (m_mouse_pos);
|
||||
|
||||
for (std::list<ViewService *>::iterator g = m_grabbed.begin (); !done && g != m_grabbed.end (); ) {
|
||||
std::list<ViewService *>::iterator gg = g;
|
||||
|
|
@ -614,6 +624,7 @@ void
|
|||
ViewObjectWidget::mouseDoubleClickEvent (QMouseEvent *e)
|
||||
{
|
||||
BEGIN_PROTECTED
|
||||
ensure_entered ();
|
||||
begin_mouse_event (lay::Cursor::none);
|
||||
|
||||
setFocus ();
|
||||
|
|
@ -626,7 +637,7 @@ BEGIN_PROTECTED
|
|||
|
||||
unsigned int buttons = qt_to_buttons (e->buttons (), e->modifiers ());
|
||||
|
||||
db::DPoint p = m_trans.inverted () * db::DPoint (e->pos ().x (), height () - 1 - e->pos ().y ());
|
||||
db::DPoint p = pixel_to_um (e->pos ());
|
||||
|
||||
for (std::list<ViewService *>::iterator g = m_grabbed.begin (); !done && g != m_grabbed.end (); ) {
|
||||
std::list<ViewService *>::iterator gg = g;
|
||||
|
|
@ -659,6 +670,8 @@ void
|
|||
ViewObjectWidget::enterEvent (QEvent * /*event*/)
|
||||
{
|
||||
BEGIN_PROTECTED
|
||||
m_mouse_inside = true;
|
||||
|
||||
begin_mouse_event ();
|
||||
|
||||
bool done = false;
|
||||
|
|
@ -723,12 +736,15 @@ BEGIN_PROTECTED
|
|||
|
||||
end_mouse_event ();
|
||||
END_PROTECTED
|
||||
|
||||
m_mouse_inside = false;
|
||||
}
|
||||
|
||||
void
|
||||
ViewObjectWidget::wheelEvent (QWheelEvent *e)
|
||||
{
|
||||
BEGIN_PROTECTED
|
||||
ensure_entered ();
|
||||
begin_mouse_event ();
|
||||
|
||||
e->ignore ();
|
||||
|
|
@ -738,7 +754,7 @@ BEGIN_PROTECTED
|
|||
unsigned int buttons = qt_to_buttons (e->buttons (), e->modifiers ());
|
||||
bool horizonal = (e->orientation () == Qt::Horizontal);
|
||||
|
||||
db::DPoint p = m_trans.inverted () * db::DPoint (e->pos ().x (), height () - 1 - e->pos ().y ());
|
||||
db::DPoint p = pixel_to_um (e->pos ());
|
||||
|
||||
for (std::list<ViewService *>::iterator g = m_grabbed.begin (); !done && g != m_grabbed.end (); ) {
|
||||
std::list<ViewService *>::iterator gg = g;
|
||||
|
|
@ -770,6 +786,7 @@ END_PROTECTED
|
|||
void
|
||||
ViewObjectWidget::mousePressEvent (QMouseEvent *e)
|
||||
{
|
||||
ensure_entered ();
|
||||
setFocus ();
|
||||
|
||||
m_mouse_pos = e->pos ();
|
||||
|
|
@ -784,12 +801,13 @@ void
|
|||
ViewObjectWidget::mouseReleaseEvent (QMouseEvent *e)
|
||||
{
|
||||
BEGIN_PROTECTED
|
||||
ensure_entered ();
|
||||
begin_mouse_event ();
|
||||
|
||||
bool done = false;
|
||||
|
||||
m_mouse_pos = e->pos ();
|
||||
db::DPoint p = m_trans.inverted () * db::DPoint (e->pos ().x (), height () - 1 - e->pos ().y ());
|
||||
db::DPoint p = pixel_to_um (e->pos ());
|
||||
|
||||
for (std::list<ViewService *>::iterator g = m_grabbed.begin (); !done && g != m_grabbed.end (); ) {
|
||||
std::list<ViewService *>::iterator gg = g;
|
||||
|
|
@ -838,6 +856,12 @@ END_PROTECTED
|
|||
m_mouse_pressed_state = false;
|
||||
}
|
||||
|
||||
db::DPoint
|
||||
ViewObjectWidget::pixel_to_um (const QPoint &pt) const
|
||||
{
|
||||
return m_trans.inverted () * db::DPoint (pt.x (), height () - 1 - pt.y ());
|
||||
}
|
||||
|
||||
void
|
||||
ViewObjectWidget::mouse_event_trans (const db::DCplxTrans &trans)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -962,6 +962,35 @@ public:
|
|||
return m_view_objects_dismissed;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Gets the current mouse position
|
||||
*/
|
||||
QPoint mouse_position () const
|
||||
{
|
||||
return m_mouse_pos;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Gets the current mouse position in micrometer units
|
||||
*/
|
||||
db::DPoint mouse_position_um () const
|
||||
{
|
||||
return pixel_to_um (m_mouse_pos);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Translates a screen coordinate in micrometer coordinates
|
||||
*/
|
||||
db::DPoint pixel_to_um (const QPoint &pt) const;
|
||||
|
||||
/**
|
||||
* @brief Gets a flag indicating whether the mouse is inside the window
|
||||
*/
|
||||
bool mouse_in_window () const
|
||||
{
|
||||
return m_mouse_inside;
|
||||
}
|
||||
|
||||
protected:
|
||||
/**
|
||||
* @brief Qt focus event handler
|
||||
|
|
@ -1052,8 +1081,10 @@ private:
|
|||
bool m_mouse_pressed_state;
|
||||
unsigned int m_mouse_buttons;
|
||||
bool m_in_mouse_move;
|
||||
bool m_mouse_inside;
|
||||
lay::Cursor::cursor_shape m_cursor, m_default_cursor;
|
||||
|
||||
void ensure_entered ();
|
||||
void do_mouse_move ();
|
||||
void begin_mouse_event (lay::Cursor::cursor_shape cursor = lay::Cursor::keep);
|
||||
void end_mouse_event ();
|
||||
|
|
|
|||
Loading…
Reference in New Issue