WIP: preparations for a non-Qt event loop protocol

This commit is contained in:
Matthias Koefferlein 2022-05-07 23:44:08 +02:00
parent 42f0a79dee
commit 1ad9dd2c11
12 changed files with 252 additions and 39 deletions

View File

@ -1593,6 +1593,34 @@ Class<lay::LayoutView> decl_LayoutView (QT_EXTERNAL_BASE (QWidget) "lay", "Layou
"Returns an array of \\LayerPropertiesIterator objects pointing to the currently selected layers. "
"If no layer view is selected currently, an empty array is returned.\n"
) +
#if !defined(HAVE_QT)
gsi::event ("on_image_updated_event", static_cast<tl::Event (lay::LayoutView::*)> (&lay::LayoutView::image_updated_event),
"@brief An event indicating that the image (\"screenshot\") was updated\n"
"\n"
"This event is triggered when calling \\timer."
"\n"
"This event has been introduced in version 0.28."
) +
gsi::event ("on_drawing_finished_event", static_cast<tl::Event (lay::LayoutView::*)> (&lay::LayoutView::drawing_finished_event),
"@brief An event indicating that the image is fully drawn\n"
"\n"
"This event is triggered when calling \\timer. "
"Before this event is issue, a final \\on_image_updated_event may be issued.\n"
"\n"
"This event has been introduced in version 0.28."
) +
gsi::method ("timer", static_cast<void (lay::LayoutView::*) ()> (&lay::LayoutView::timer),
"@brief A callback required to be called regularily in the non-Qt case.\n"
"\n"
"This callback eventually implements the event loop in the non-Qt case. The main task "
"is to indicate new versions of the layout image while it is drawn. "
"When a new image has arrived, this method will issue an \\on_image_updated_event. "
"In the implementation of the latter, \"screenshot\" may be called to retrieve the current image.\n"
"When drawing has finished, the \\on_drawing_finished_event will be triggered.\n"
"\n"
"This method has been introduced in version 0.28."
) +
#endif
gsi::event ("on_active_cellview_changed", static_cast<tl::Event (lay::LayoutView::*)> (&lay::LayoutView::active_cellview_changed_event),
"@brief An event indicating that the active cellview has changed\n"
"\n"

View File

@ -912,7 +912,51 @@ Class<gsi::ButtonStateNamespace> decl_ButtonState ("lay", "ButtonState",
"This class has been introduced in version 0.22.\n"
);
static std::vector<std::string>
class KeyCodesNamespace { };
static int const_KeyEscape() { return (int) lay::KeyEscape; }
static int const_KeyTab() { return (int) lay::KeyTab; }
static int const_KeyBacktab() { return (int) lay::KeyBacktab; }
static int const_KeyBackspace() { return (int) lay::KeyBackspace; }
static int const_KeyReturn() { return (int) lay::KeyReturn; }
static int const_KeyEnter() { return (int) lay::KeyEnter; }
static int const_KeyInsert() { return (int) lay::KeyInsert; }
static int const_KeyDelete() { return (int) lay::KeyDelete; }
static int const_KeyHome() { return (int) lay::KeyHome; }
static int const_KeyEnd() { return (int) lay::KeyEnd; }
static int const_KeyDown() { return (int) lay::KeyDown; }
static int const_KeyUp() { return (int) lay::KeyUp; }
static int const_KeyLeft() { return (int) lay::KeyLeft; }
static int const_KeyRight() { return (int) lay::KeyRight; }
static int const_KeyPageUp() { return (int) lay::KeyPageUp; }
static int const_KeyPageDown() { return (int) lay::KeyPageDown; }
Class<gsi::KeyCodesNamespace> decl_KeyCode ("lay", "KeyCode",
method ("Escape", &const_KeyEscape, "@brief Indicates the Escape key") +
method ("Tab", &const_KeyTab, "@brief Indicates the Tab key") +
method ("Backtab", &const_KeyBacktab, "@brief Indicates the Backtab key") +
method ("Backspace", &const_KeyBackspace, "@brief Indicates the Backspace key") +
method ("Return", &const_KeyReturn, "@brief Indicates the Return key") +
method ("Enter", &const_KeyEnter, "@brief Indicates the Enter key") +
method ("Insert", &const_KeyInsert, "@brief Indicates the Insert key") +
method ("Delete", &const_KeyDelete, "@brief Indicates the Delete key") +
method ("Home", &const_KeyHome, "@brief Indicates the Home key") +
method ("End", &const_KeyEnd, "@brief Indicates the End key") +
method ("Down", &const_KeyDown, "@brief Indicates the Down key") +
method ("Up", &const_KeyUp, "@brief Indicates the Up key") +
method ("Left", &const_KeyLeft, "@brief Indicates the Left key") +
method ("Right", &const_KeyRight, "@brief Indicates the Right key") +
method ("PageUp", &const_KeyPageUp, "@brief Indicates the PageUp key") +
method ("PageDown", &const_KeyPageDown, "@brief Indicates the PageDown key"),
"@brief The namespace for the some key codes.\n"
"This namespace defines some key codes understood by built-in \\LayoutView components. "
"When compiling with Qt, these codes are compatible with Qt's key codes.\n"
"The key codes are intended to be used when directly interfacing with \\LayoutView in non-Qt-based environments.\n"
"\n"
"This class has been introduced in version 0.28.\n"
);
static std::vector<std::string>
get_config_names (lay::Dispatcher *dispatcher)
{
std::vector<std::string> names;

View File

@ -23,7 +23,7 @@
#include "layCellView.h"
#include "layLayoutView.h"
#if defined(HAVE_QT) // @@@
#if defined(HAVE_QT)
# include "layStream.h"
#endif
#include "dbLayout.h"
@ -292,7 +292,7 @@ LayoutHandle::set_save_options (const db::SaveLayoutOptions &options, bool valid
void
LayoutHandle::update_save_options (db::SaveLayoutOptions &options)
{
#if defined(HAVE_QT) // @@@
#if defined(HAVE_QT)
for (tl::Registrar<lay::PluginDeclaration>::iterator cls = tl::Registrar<lay::PluginDeclaration>::begin (); cls != tl::Registrar<lay::PluginDeclaration>::end (); ++cls) {
const lay::StreamWriterPluginDeclaration *decl = dynamic_cast <const lay::StreamWriterPluginDeclaration *> (&*cls);

View File

@ -296,6 +296,7 @@ LayoutCanvas::LayoutCanvas (lay::LayoutViewBase *view)
m_redraw_clearing (false),
m_redraw_force_update (true),
m_update_image (true),
m_drawing_finished (false),
m_do_update_image_dm (this, &LayoutCanvas::do_update_image),
m_do_end_of_drawing_dm (this, &LayoutCanvas::do_end_of_drawing),
m_image_cache_size (1)
@ -358,23 +359,23 @@ LayoutCanvas::key_event (unsigned int key, unsigned int buttons)
{
#if defined(HAVE_QT) // @@@
if (! (buttons & lay::ShiftButton)) {
if (int (key) == Qt::Key_Down) {
if (int (key) == lay::KeyDown) {
emit down_arrow_key_pressed ();
} else if (int (key) == Qt::Key_Up) {
} else if (int (key) == lay::KeyUp) {
emit up_arrow_key_pressed ();
} else if (int (key) == Qt::Key_Left) {
} else if (int (key) == lay::KeyLeft) {
emit left_arrow_key_pressed ();
} else if (int (key) == Qt::Key_Right) {
} else if (int (key) == lay::KeyRight) {
emit right_arrow_key_pressed ();
}
} else {
if (int (key) == Qt::Key_Down) {
if (int (key) == lay::KeyDown) {
emit down_arrow_key_pressed_with_shift ();
} else if (int (key) == Qt::Key_Up) {
} else if (int (key) == lay::KeyUp) {
emit up_arrow_key_pressed_with_shift ();
} else if (int (key) == Qt::Key_Left) {
} else if (int (key) == lay::KeyLeft) {
emit left_arrow_key_pressed_with_shift ();
} else if (int (key) == Qt::Key_Right) {
} else if (int (key) == lay::KeyRight) {
emit right_arrow_key_pressed_with_shift ();
}
}
@ -1017,13 +1018,12 @@ LayoutCanvas::resizeEvent (QResizeEvent *)
void
LayoutCanvas::resize (unsigned int width, unsigned int height)
{
// pass down to the basic view object canvas
lay::ViewObjectWidget::resize (width, height);
// don't wait until the layout system informs us - which may never take place when
// the widget isn't shown.
do_resize (width, height);
#if defined(HAVE_QT)
QWidget::resize (width, height);
#endif
}
void
@ -1093,6 +1093,14 @@ LayoutCanvas::zoom_trans (const db::DCplxTrans &trans)
update_viewport ();
}
bool
LayoutCanvas::drawing_finished ()
{
bool f = m_drawing_finished;
m_drawing_finished = false;
return f;
}
void
LayoutCanvas::do_end_of_drawing ()
{
@ -1109,6 +1117,8 @@ LayoutCanvas::do_end_of_drawing ()
}
set_default_cursor (lay::Cursor::none);
m_drawing_finished = true;
}
void

View File

@ -346,6 +346,11 @@ public:
*/
void resize (unsigned int width, unsigned int height);
/**
* @brief Gets (and resets) a flag indicating that drawing has finished
*/
bool drawing_finished ();
/**
* @brief An event indicating that the viewport was changed.
* If the viewport (the rectangle that is shown) changes, this event is fired.
@ -385,6 +390,7 @@ private:
bool m_redraw_clearing;
bool m_redraw_force_update;
bool m_update_image;
bool m_drawing_finished;
std::vector<int> m_need_redraw_layer;
std::vector<lay::RedrawLayerInfo> m_layers;

View File

@ -1128,6 +1128,26 @@ LayoutView::LayoutView (lay::LayoutView *source, db::Manager *mgr, bool editable
// .. nothing yet ..
}
// NOTE: this methods needs to be called "frequently"
void
LayoutView::timer ()
{
LayoutViewBase::timer ();
// Without Qt, this is also the opportunity to execute deferred methods
tl::DeferredMethodScheduler::execute ();
// We also issue the "image_updated" event if the image ("screenshot") has been updated
if (canvas ()->image_updated ()) {
image_updated_event ();
}
// And also the drawing_finished event
if (canvas ()->drawing_finished ()) {
drawing_finished_event ();
}
}
} // namespace lay
#endif

View File

@ -794,6 +794,21 @@ public:
*/
LayoutView (lay::LayoutView *source, db::Manager *mgr, bool editable, lay::Plugin *plugin_parent, unsigned int options = (unsigned int) LV_Normal);
/**
* @brief This event is triggered in the "timer" callback when the image ("screenshot") was updated.
*/
tl::Event image_updated_event;
/**
* @brief This event is triggered in the "timer" callback when the drawing thread has finished.
*/
tl::Event drawing_finished_event;
/**
* @brief A callback that needs to be called "frequently"
*/
void timer ();
protected:
/**
* @brief Gets the LayoutView interface

View File

@ -34,6 +34,7 @@
#include "tlLog.h"
#include "tlAssert.h"
#include "tlExceptions.h"
#include "tlDeferredExecution.h"
#include "layLayoutViewBase.h"
#include "layViewOp.h"
#include "layViewObject.h"
@ -3357,7 +3358,7 @@ LayoutViewBase::get_ui ()
return mp_ui;
}
// @@@ needs to be called "as often as possible"
// NOTE: this methods needs to be called "frequently"
void
LayoutViewBase::timer ()
{

View File

@ -2762,6 +2762,11 @@ protected:
virtual LayoutView *get_ui ();
lay::LayoutCanvas *canvas ()
{
return mp_canvas;
}
bool configure (const std::string &name, const std::string &value);
void config_finalize ();

View File

@ -89,17 +89,15 @@ bool
MoveService::key_event (unsigned int key, unsigned int /*buttons*/)
{
double dx = 0.0, dy = 0.0;
#if defined(HAVE_QT) // @@@
if (int (key) == Qt::Key_Down) {
if (int (key) == lay::KeyDown) {
dy = -1.0;
} else if (int (key) == Qt::Key_Up) {
} else if (int (key) == lay::KeyUp) {
dy = 1.0;
} else if (int (key) == Qt::Key_Left) {
} else if (int (key) == lay::KeyLeft) {
dx = -1.0;
} else if (int (key) == Qt::Key_Right) {
} else if (int (key) == lay::KeyRight) {
dx = 1.0;
}
#endif
if (! m_dragging && fabs (dx + dy) > 0.0 && mp_editables->has_selection ()) {

View File

@ -232,9 +232,7 @@ ViewObject::redraw ()
if (m_static) {
widget ()->touch ();
} else {
#if defined(HAVE_QT)
widget ()->update (); // @@@
#endif
widget ()->update ();
}
}
}
@ -287,9 +285,9 @@ ViewService::set_cursor (lay::Cursor::cursor_shape cursor)
}
// ---------------------------------------------------------------
// ViewObject implementation
// ViewObjectWidget implementation
#if defined(HAVE_QT) // @@@
#if defined(HAVE_QT)
ViewObjectWidget::ViewObjectWidget (QWidget *parent, const char *name)
: QWidget (parent),
m_view_objects_dismissed (false),
@ -301,7 +299,10 @@ ViewObjectWidget::ViewObjectWidget (QWidget *parent, const char *name)
m_in_mouse_move (false),
m_mouse_inside (false),
m_cursor (lay::Cursor::none),
m_default_cursor (lay::Cursor::none)
m_default_cursor (lay::Cursor::none),
m_widget_width (0),
m_widget_height (0),
m_image_updated (false)
{
setMouseTracking (true);
setObjectName (QString::fromUtf8 (name));
@ -320,7 +321,10 @@ ViewObjectWidget::ViewObjectWidget ()
m_in_mouse_move (false),
m_mouse_inside (false),
m_cursor (lay::Cursor::none),
m_default_cursor (lay::Cursor::none)
m_default_cursor (lay::Cursor::none),
m_widget_width (500),
m_widget_height (500),
m_image_updated (false)
{
m_objects.changed ().add (this, &ViewObjectWidget::objects_changed);
}
@ -395,7 +399,7 @@ ViewObjectWidget::set_cursor (lay::Cursor::cursor_shape cursor)
void
ViewObjectWidget::set_default_cursor (lay::Cursor::cursor_shape cursor)
{
#if defined(HAVE_QT) // @@@
#if defined(HAVE_QT)
if (cursor != m_default_cursor) {
m_default_cursor = cursor;
if (m_cursor == lay::Cursor::none) {
@ -920,13 +924,23 @@ END_PROTECTED
}
#endif
void
ViewObjectWidget::resize (unsigned int w, unsigned int h)
{
m_widget_width = w;
m_widget_height = h;
#if defined(HAVE_QT)
QWidget::resize (w, h);
#endif
}
int
ViewObjectWidget::widget_height () const
{
#if defined(HAVE_QT)
return height ();
#else
return 500; // @@@
return m_widget_height;
#endif
}
@ -936,7 +950,7 @@ ViewObjectWidget::widget_width () const
#if defined(HAVE_QT)
return width ();
#else
return 800; // @@@
return m_widget_width;
#endif
}
@ -1078,7 +1092,16 @@ ViewObjectWidget::thaw (ViewObject *obj)
void
ViewObjectWidget::update ()
{
// @@@
// NOTE: this does not need to be thread-safe as we make sure (as in Qt) that update() is always called from the main thread.
m_image_updated = true;
}
bool
ViewObjectWidget::image_updated ()
{
bool f = m_image_updated;
m_image_updated = false;
return f;
}
#endif

View File

@ -638,12 +638,53 @@ private:
* @brief Describes the button state (supposed to be ored)
*/
enum ButtonState {
ShiftButton = 1,
ShiftButton = 1,
ControlButton = 2,
AltButton = 4,
LeftButton = 8,
MidButton = 16,
RightButton = 32
AltButton = 4,
LeftButton = 8,
MidButton = 16,
RightButton = 32
};
/**
* @brief Key codes for keys understood by the standard components
*/
enum KeyCodes {
#if defined(HAVE_QT)
KeyEscape = int(Qt::Key_Escape),
KeyTab = int(Qt::Key_Tab),
KeyBacktab = int(Qt::Key_Backtab),
KeyBackspace = int(Qt::Key_Backspace),
KeyReturn = int(Qt::Key_Return),
KeyEnter = int(Qt::Key_Enter),
KeyInsert = int(Qt::Key_Insert),
KeyDelete = int(Qt::Key_Delete),
KeyHome = int(Qt::Key_Home),
KeyEnd = int(Qt::Key_End),
KeyDown = int(Qt::Key_Down),
KeyUp = int(Qt::Key_Up),
KeyLeft = int(Qt::Key_Left),
KeyRight = int(Qt::Key_Right),
KeyPageUp = int(Qt::Key_PageUp),
KeyPageDown = int(Qt::Key_PageDown)
#else
KeyEscape = 0x01000000,
KeyTab = 0x01000001,
KeyBacktab = 0x01000002,
KeyBackspace = 0x01000003,
KeyReturn = 0x01000004,
KeyEnter = 0x01000005,
KeyInsert = 0x01000006,
KeyDelete = 0x01000007,
KeyHome = 0x01000010,
KeyEnd = 0x01000011,
KeyLeft = 0x01000012,
KeyUp = 0x01000013,
KeyRight = 0x01000014,
KeyDown = 0x01000015,
KeyPageUp = 0x01000016,
KeyPageDown = 0x01000017
#endif
};
/**
@ -1031,6 +1072,15 @@ public:
return m_mouse_inside;
}
#if !defined(HAVE_QT)
/**
* @brief Gets a value indicating that the image data has been updated
*
* This method will return true once after "update" was called.
*/
bool image_updated ();
#endif
protected:
#if defined(HAVE_QT) // @@@
/**
@ -1103,7 +1153,13 @@ protected:
void wheelEvent (QWheelEvent *e);
#endif
#if !defined(HAVE_QT) // @@@
#if !defined(HAVE_QT)
/**
* @brief Emulates the update() method in the non-Qt case
*
* After calling this method, the next image_updated() call will return true while also resetting the
* update needed flag.
*/
void update ();
#endif
@ -1112,6 +1168,11 @@ protected:
*/
void mouse_event_trans (const db::DCplxTrans &trans);
/**
* @brief Resizes the widget
*/
void resize (unsigned int w, unsigned int h);
private:
friend class lay::ViewObject;
friend class lay::ViewService;
@ -1133,6 +1194,8 @@ private:
bool m_in_mouse_move;
bool m_mouse_inside;
lay::Cursor::cursor_shape m_cursor, m_default_cursor;
unsigned int m_widget_width, m_widget_height;
bool m_image_updated;
void ensure_entered ();
void do_mouse_move ();