55 #include <sys/types.h> 63 #include "rnr/rnrconfig.h" 70 #include "opencv2/core/core.hpp" 71 #include "opencv2/highgui/highgui.hpp" 75 #include <gdk/gdkkeysyms.h> 85 typedef struct _CvImageWidget CvImageWidget;
86 extern GtkWidget *cvImageWidgetNew(
int flags);
87 extern void cvImageWidgetSetImage(CvImageWidget *widget,
const CvArr *arr);
94 WinGtk::WinGtk(
const string &strWinName,
98 Win(strWinName, nWidth, nHeight, bDecorate)
101 const int nHBoxBorder = 6;
102 const int nMenuWidth = 48;
103 const int nStatusBarHeight = 20;
104 const int nWorkspaceBorder = 4;
107 int nWorkspaceHeight = nHeight - nStatusBarHeight;
113 nWorkspaceWidth = nWidth - (nHBoxBorder + nMenuWidth + nWorkspaceBorder) * 2;
114 nWorkspaceHeight = nHeight - nHBoxBorder - nStatusBarHeight
124 m_wMain = gtk_window_new(GTK_WINDOW_TOPLEVEL);
149 wHBox = gtk_hbox_new(FALSE, 0);
150 gtk_container_set_border_width(GTK_CONTAINER(wHBox), nHBoxBorder);
151 gtk_box_pack_start(GTK_BOX(
m_wContainer), wHBox, FALSE, FALSE, 0);
156 w = gtk_vbutton_box_new();
157 gtk_button_box_set_layout(GTK_BUTTON_BOX(w), GTK_BUTTONBOX_START);
158 g_object_set(G_OBJECT(w),
159 "width-request", nMenuWidth,
160 "height-request", nWorkspaceHeight,
162 gtk_container_set_border_width(GTK_CONTAINER(w), 2);
163 gtk_button_box_set_child_size(GTK_BUTTON_BOX(w), nMenuWidth, nMenuWidth);
164 gtk_button_box_set_child_ipadding(GTK_BUTTON_BOX(w), 0, 0);
165 gtk_box_set_spacing(GTK_BOX(w), 1);
166 gtk_box_pack_start(GTK_BOX(wHBox), w, TRUE, TRUE, 0);
174 "width-request", nWorkspaceWidth,
175 "height-request", nWorkspaceHeight,
179 gtk_container_set_border_width(GTK_CONTAINER(
m_wWorkspace), nWorkspaceBorder);
180 gtk_box_pack_start(GTK_BOX(wHBox),
m_wWorkspace, FALSE, FALSE, 0);
181 m_rectWorkspace = cvRect(nMenuWidth, 0, nWorkspaceWidth, nWorkspaceHeight);
192 w = gtk_vbutton_box_new();
193 gtk_button_box_set_layout(GTK_BUTTON_BOX(w), GTK_BUTTONBOX_START);
194 g_object_set(G_OBJECT(w),
195 "width-request", nMenuWidth,
196 "height-request", nWorkspaceHeight,
198 gtk_button_box_set_child_size(GTK_BUTTON_BOX(w), nMenuWidth, nMenuWidth);
199 gtk_button_box_set_child_ipadding(GTK_BUTTON_BOX(w), 0, 0);
200 gtk_box_set_spacing(GTK_BOX(w), 1);
201 gtk_box_pack_start(GTK_BOX(wHBox), w, TRUE, TRUE, 0);
209 "width-request", nWorkspaceWidth,
222 wHBox = gtk_hbox_new(FALSE, 0);
227 gtk_widget_modify_fg(
m_wPageRef, GTK_STATE_NORMAL,
229 gtk_widget_modify_bg(
m_wPageRef, GTK_STATE_NORMAL,
232 "width-request", nMenuWidth,
233 "height-request", nStatusBarHeight,
235 gtk_label_set_justify(GTK_LABEL(
m_wPageRef), GTK_JUSTIFY_LEFT);
236 gtk_box_pack_start(GTK_BOX(wHBox),
m_wPageRef, FALSE, FALSE, 4);
245 "width-request", nWorkspaceWidth-nMenuWidth,
246 "height-request", nStatusBarHeight,
248 gtk_label_set_justify(GTK_LABEL(
m_wStatusBar), GTK_JUSTIFY_LEFT);
250 gtk_box_pack_start(GTK_BOX(wHBox),
m_wStatusBar, FALSE, FALSE, 4);
255 gtk_signal_connect(GTK_OBJECT(
m_wMain),
"key-press-event",
265 MapPangoFont_T::iterator iter;
272 pango_font_description_free(iter->second);
277 const std::string &strVal)
280 PangoFontDescription *pFont;
284 if( strKey.find(
"color") == 0 )
286 gdk_color_parse(strVal.c_str(), &color);
289 if( strKey ==
"color_win_bg" )
291 gtk_widget_modify_bg(
m_wMain, GTK_STATE_NORMAL, &color);
292 gtk_widget_modify_base(
m_wMain, GTK_STATE_NORMAL, &color);
293 gtk_widget_modify_bg(
m_wWorkspace, GTK_STATE_NORMAL, &color);
295 else if( strKey ==
"color_status_fg" )
297 gtk_widget_modify_fg(
m_wPageRef, GTK_STATE_NORMAL, &color);
298 gtk_widget_modify_fg(
m_wStatusBar, GTK_STATE_NORMAL, &color);
300 else if( strKey ==
"color_status_bg" )
303 else if( strKey ==
"color_status_border" )
307 else if( strKey ==
"color_button_bg" )
313 gtk_widget_modify_bg(
m_mapBttns[i][j].m_wBttn, GTK_STATE_NORMAL,
315 gtk_widget_modify_bg(
m_mapBttns[i][j].m_wBttn, GTK_STATE_INSENSITIVE,
322 else if( strKey.find(
"font") == 0 )
324 pFont = pango_font_description_from_string(strVal.c_str());
335 uint_t i = uImgIndex;
337 cvImageWidgetSetImage((CvImageWidget *)
m_wCvImage[i], &img);
353 LOGERROR(
"Workspace has no CvImage[%u] widget.", uImgIndex);
362 snprintf(buf,
sizeof(buf),
"%d", nPageRef);
363 buf[
sizeof(buf)-1] = 0;
365 gtk_label_set_text(GTK_LABEL(
m_wPageRef), buf);
371 if( !strPageRef.empty() )
373 gtk_label_set_text(GTK_LABEL(
m_wPageRef), strPageRef.c_str());
385 vsnprintf(buf,
sizeof(buf), sFmt, ap);
386 buf[
sizeof(buf)-1] = 0;
415 while( gtk_main_iteration_do(FALSE) &&
425 g_source_remove(timer);
455 while( gtk_main_iteration_do(FALSE) && !expired && !
m_bMouseEvent );
460 g_source_remove(timer);
477 while( gtk_main_iteration_do(FALSE) && !expired );
482 const string &strIconPath,
483 const string &strAltText,
484 const string &strToolTip)
486 GtkWidget *wBttnImg = NULL;
489 if( !strIconPath.empty() && (access(strIconPath.c_str(), F_OK|R_OK) == 0) )
491 wBttnImg = gtk_image_new_from_file(strIconPath.c_str());
494 if( wBttnImg == NULL )
499 wBttn = gtk_button_new();
501 gtk_widget_modify_bg(wBttn, GTK_STATE_NORMAL,
503 gtk_widget_modify_bg(wBttn, GTK_STATE_INSENSITIVE,
505 gtk_button_set_image(GTK_BUTTON(wBttn), wBttnImg);
506 gtk_widget_set_tooltip_text(wBttn,
507 strToolTip.empty()? NULL: strToolTip.c_str());
509 return addButton(nBttnId, eAlign, wBttn);
515 const string &strAltText,
516 const string &strToolTip)
520 if( wBttnImg != NULL )
522 wBttn = gtk_button_new();
523 gtk_widget_modify_bg(wBttn, GTK_STATE_NORMAL,
525 gtk_widget_modify_bg(wBttn, GTK_STATE_INSENSITIVE,
527 gtk_button_set_image(GTK_BUTTON(wBttn), (GtkWidget *)wBttnImg);
528 gtk_widget_set_tooltip_text(wBttn,
529 strToolTip.empty()? NULL: strToolTip.c_str());
531 return addButton(nBttnId, eAlign, wBttn);
541 const string &strLabel,
542 const string &strToolTip)
546 if( !strLabel.empty() )
548 wBttn = gtk_button_new_with_label(strLabel.c_str());
553 snprintf(buf,
sizeof(buf),
"Bttn %d", nBttnId);
554 buf[
sizeof(buf)-1] = 0;
555 wBttn = gtk_button_new_with_label(buf);
558 gtk_widget_modify_bg(wBttn, GTK_STATE_NORMAL,
560 gtk_widget_modify_bg(wBttn, GTK_STATE_INSENSITIVE,
562 gtk_widget_set_tooltip_text(wBttn,
563 strToolTip.empty()? NULL: strToolTip.c_str());
565 return addButton(nBttnId, eAlign, wBttn);
581 gtk_signal_connect(GTK_OBJECT(wBttn),
"clicked",
585 gtk_box_pack_start(GTK_BOX(
m_wBttnMenu[n]), wBttn, TRUE, TRUE, 0);
591 gtk_button_set_alignment(GTK_BUTTON(wBttn), 0.5, 0.5);
600 gtk_widget_show(wBttn);
602 gtk_widget_queue_draw( GTK_WIDGET(wBttn) );
608 const string &strIconPath,
609 const string &strToolTip)
611 MapBttns_T::iterator pos;
612 GtkWidget *wBttnImg = NULL;
620 if( !strIconPath.empty() && (access(strIconPath.c_str(), F_OK|R_OK) == 0) )
622 wBttnImg = gtk_image_new_from_file(strIconPath.c_str());
625 if( wBttnImg == NULL )
630 wBttn = pos->second.m_wBttn;
632 gtk_button_set_image(GTK_BUTTON(wBttn), wBttnImg);
634 gtk_widget_set_tooltip_text(wBttn,
635 strToolTip.empty()? NULL: strToolTip.c_str());
638 gtk_widget_show(wBttn);
646 const string &strToolTip)
648 MapBttns_T::iterator pos;
656 wBttn = pos->second.m_wBttn;
658 gtk_button_set_image(GTK_BUTTON(wBttn), (GtkWidget *)wBttnImg);
660 gtk_widget_set_tooltip_text(wBttn,
661 strToolTip.empty()? NULL: strToolTip.c_str());
664 gtk_widget_show(wBttn);
671 const std::string &strLabel,
672 const std::string &strToolTip)
674 MapBttns_T::iterator pos;
682 wBttn = pos->second.m_wBttn;
684 gtk_button_set_label(GTK_BUTTON(wBttn), strLabel.c_str());
686 gtk_widget_set_tooltip_text(wBttn,
687 strToolTip.empty()? NULL: strToolTip.c_str());
690 gtk_widget_show(wBttn);
698 MapBttns_T::iterator pos;
715 wBttn = pos->second.m_wBttn;
721 gtk_button_set_image(GTK_BUTTON(wBttn), NULL);
724 gtk_container_remove(GTK_CONTAINER(
m_wBttnMenu[n]), wBttn);
737 MapBttns_T::iterator iter;
745 wBttn = iter->second.m_wBttn;
751 gtk_button_set_image(GTK_BUTTON(wBttn), NULL);
754 gtk_container_remove(GTK_CONTAINER(
m_wBttnMenu[n]), wBttn);
765 MapBttns_T::iterator pos;
775 gtk_widget_set_sensitive(pos->second.m_wBttn, TRUE);
776 gtk_widget_set_state(pos->second.m_wBttn, GTK_STATE_NORMAL);
779 gtk_widget_set_sensitive(pos->second.m_wBttn, TRUE);
780 gtk_widget_set_state(pos->second.m_wBttn, GTK_STATE_ACTIVE);
783 gtk_widget_set_sensitive(pos->second.m_wBttn, FALSE);
789 gtk_widget_show_all(pos->second.m_wBttn);
808 m_wCvImage[0] = cvImageWidgetNew(CV_WINDOW_AUTOSIZE);
814 wAlign = gtk_alignment_new(0.5, 0.0, 0, 0);
815 gtk_box_pack_start(GTK_BOX(
m_wWorkspace), wAlign, TRUE, TRUE, 0);
849 "width-request", sizeVidWin.width,
850 "height-request", sizeVidWin.height,
852 gtk_widget_modify_bg(
m_wGstWin, GTK_STATE_NORMAL,
854 gtk_widget_modify_bg(
m_wGstWin, GTK_STATE_ACTIVE,
856 gtk_widget_modify_bg(
m_wGstWin, GTK_STATE_SELECTED,
859 gtk_widget_set_double_buffered(
m_wGstWin, FALSE);
876 LOGERROR(
"Cannot determine xid.");
882 GtkWidget *wBox = (GtkWidget *)wContainer;
893 if( i >= MaxCvImages )
895 LOGERROR(
"No more CvImage displays available.");
900 m_wCvImage[i] = cvImageWidgetNew(CV_WINDOW_AUTOSIZE);
923 gtk_container_remove(GTK_CONTAINER(
m_wCvImageBox[uImgIndex]),
953 PangoFontDescription *pFont;
954 MapLookFeel_T::iterator iter;
958 if( iter->first.find(
"color") == 0 )
960 gdk_color_parse(iter->second.c_str(), &color);
963 else if( iter->first.find(
"font") == 0 )
965 pFont = pango_font_description_from_string(iter->second.c_str());
973 uint_t i = uImgIndex;
975 gtk_widget_modify_bg(
m_wCvImage[i], GTK_STATE_NORMAL,
978 gtk_signal_connect(GTK_OBJECT(
m_wCvImage[i]),
"button-press-event",
980 gtk_signal_connect(GTK_OBJECT(
m_wCvImage[i]),
"button-release-event",
982 gtk_signal_connect(GTK_OBJECT(
m_wCvImage[i]),
"motion-notify-event",
987 gtk_widget_queue_draw(GTK_WIDGET(
m_wCvImage[i]));
992 GtkWidget *wContainer = (GtkWidget *)user_data;
993 gtk_container_remove(GTK_CONTAINER(wContainer), w);
998 *(
int *)user_data = 1;
1004 gpointer *user_data)
1010 switch( event->keyval )
1023 code =
event->keyval;
1027 pWin->
m_uLastKey = (code & 0xffff) | (event->state << 16);
1039 gpointer *user_data)
1043 CvPoint2D32f pt32f = {-1., -1.};
1044 CvPoint pt = {-1,-1};
1049 if( event->type == GDK_MOTION_NOTIFY )
1051 GdkEventMotion* event_motion = (GdkEventMotion*)event;
1053 cv_event = CV_EVENT_MOUSEMOVE;
1054 pt32f.x = cvRound(event_motion->x);
1055 pt32f.y = cvRound(event_motion->y);
1056 state = event_motion->state;
1059 else if( event->type == GDK_BUTTON_PRESS ||
1060 event->type == GDK_BUTTON_RELEASE ||
1061 event->type == GDK_2BUTTON_PRESS )
1063 GdkEventButton* event_button = (GdkEventButton*)event;
1065 pt32f.x = cvRound(event_button->x);
1066 pt32f.y = cvRound(event_button->y);
1068 if( event_button->type == GDK_BUTTON_PRESS )
1070 cv_event = event_button->button == 1 ? CV_EVENT_LBUTTONDOWN :
1071 event_button->button == 2 ? CV_EVENT_MBUTTONDOWN :
1072 event_button->button == 3 ? CV_EVENT_RBUTTONDOWN : 0;
1074 else if( event_button->type == GDK_BUTTON_RELEASE )
1076 cv_event = event_button->button == 1 ? CV_EVENT_LBUTTONUP :
1077 event_button->button == 2 ? CV_EVENT_MBUTTONUP :
1078 event_button->button == 3 ? CV_EVENT_RBUTTONUP : 0;
1080 else if( event_button->type == GDK_2BUTTON_PRESS )
1082 cv_event = event_button->button == 1 ? CV_EVENT_LBUTTONDBLCLK :
1083 event_button->button == 2 ? CV_EVENT_MBUTTONDBLCLK :
1084 event_button->button == 3 ? CV_EVENT_RBUTTONDBLCLK : 0;
1087 state = event_button->state;
1092 pt = cvPointFrom32f(pt32f);
1096 int flags = (state & GDK_SHIFT_MASK ? CV_EVENT_FLAG_SHIFTKEY : 0) |
1097 (state & GDK_CONTROL_MASK ? CV_EVENT_FLAG_CTRLKEY : 0) |
1098 (state & (GDK_MOD1_MASK|GDK_MOD2_MASK) ? CV_EVENT_FLAG_ALTKEY : 0) |
1099 (state & GDK_BUTTON1_MASK ? CV_EVENT_FLAG_LBUTTON : 0) |
1100 (state & GDK_BUTTON2_MASK ? CV_EVENT_FLAG_MBUTTON : 0) |
1101 (state & GDK_BUTTON3_MASK ? CV_EVENT_FLAG_RBUTTON : 0);
1142 #if GTK_CHECK_VERSION(2,18,0) 1149 if( !gdk_window_ensure_native(w->window) )
1151 LOGERROR(
"Couldn't create native window needed for GstXOverlay!");
1155 #ifdef GDK_WINDOWING_X11 1174 void rnr::WinCreate(
const char *sWinName,
int width,
int height)
1177 cvNamedWindow(sWinName, 0);
1178 cvResizeWindow(sWinName, width, height);
1182 GtkWidget *widgetCv = (GtkWidget *)cvGetWindowHandle(sWinName);
1183 GtkWindow *windowCv = GTK_WINDOW(gtk_widget_get_toplevel(widgetCv));
1186 gtk_window_set_decorated(windowCv,
false);
static gboolean onKeyPress(GtkWidget *w, GdkEventKey *event, gpointer *user_data)
Keyboard press event callback handler.
GtkWidget * m_wBttn
button widget
static const int MaxCvImages
max workspace images/video
GtkWidget * m_wCvImage[MaxCvImages]
CvImage widgets.
GtkWidget * m_wGstWin
GstWin container widget.
GtkWidget * m_wBttnMenu[NumOfButtonMenus]
left menu container widget
virtual void initWorkspaceAsGtk()
Initialize window's workspace to hold a GTK widget tree.
GtkWindow * m_wWindowMain
main widnow widget
virtual bool removeButton(int nBttnId)
Remove a button from a menu.
virtual void initWorkspaceAsGstWin(const cv::Size &sizeVidWin)
Initialize the workspace as a window display to show GStreamer video/images.
virtual void setLookAndFeel(const std::string &strKey, const std::string &strVal)
Set GUI look and feel value.
virtual void showPageRef(int nPageId)
Show page reference number.
MouseCbFunc_T m_funcMouseCb[MaxCvImages]
registered mouse cb func
virtual void showCvImage(cv::Mat &img, uint_t uImgIndex=0)
Show a OpenCV image on the workspace.
CvSize m_sizeCvImage[MaxCvImages]
size of shown CvImage
int m_nBttnId
unique button id
RoadNarrows Robotics GTK derived WinGtk window class interface.
virtual void removeAllButtons()
Remove all buttons from all menus.
virtual bool replaceButtonLabel(int nBttnId, const std::string &strLabel, const std::string &strToolTip="")
Replace existing button label with new label.
RoadNarrows Robotics Win abstract base class interface.
bool findBttn(int nBttnId, MapBttns_T::iterator &pos)
Find button.
virtual void waitMouse(int delay)
Wait for timeout or registered mouse event.
void * m_dataMouseCb[MaxCvImages]
registered mouse cb data
std::string m_strWinName
window name (and title)
virtual void showWorkspace()
Show/refresh all gui widgets in workspace.
static gboolean onAlarm(gpointer user_data)
Timeout expiry callback handler.
virtual bool replaceButtonImage(int nBttnId, const std::string &strIconPath, const std::string &strToolTip="")
Replace existing button image with new image.
uint_t m_uLastKey
last pressed keyboard code
virtual uint_t addWorkspaceCvImageDisplay(void *wContainer)
Add an OpenCV display widget to the container widget.
MapPangoFont_T m_mapFonts
look and feel font map
virtual uint_t initWorkspaceAsCvImage()
Initialize the workspace as a display to show OpenCV images.
virtual bool addButton(int nBttnId, AlignOp eAlign, GtkWidget *wBttn)
Add a GTK button widget to window button menu.
KeyCbFunc_T m_funcKeyCb
registered keyboard callback func
WinGtk window derived class.
virtual ~WinGtk()
Destructor.
static gboolean onMouseCvImage(GtkWidget *w, GdkEventKey *event, gpointer *user_data)
Mouse event on OpenCV Image widget workspace callback handler.
RoadNarrows top-level look and feel user interface declarations.
GtkWidget * m_wContainer
top container widget (hbox)
virtual bool showButtonState(int nBttnId, WidgetState eBttnState)
Show a button's widget state.
virtual void eraseWorkspace()
Remove all widgets contained in the window's workspace container.
GtkWidget * m_wMain
main widget
MapBttns_T m_mapBttns[NumOfButtonMenus]
left/right map of menu buttons.
GtkWidget * m_wStatusFrame
holds page reference and status bar
ulong_t m_uGstWinXid
GstWin container X window id.
void * m_dataKeyCb
registered keyboard callback data
int m_nWinHeight
window height
static void onRealizeGstWin(GtkWidget *w, gpointer user_data)
Realize GStreamer video window callback.
static void onButtonClick(GtkWidget *w, gpointer *user_data)
Button press event handler.
BttnCbFunc_T m_funcBttnCb
registered menu button callback func
static const int NumOfButtonMenus
left and right menus
RNR Win window abstract base class.
MapGdkColor_T m_mapColors
look and feel color map
virtual void setLookAndFeel(const std::string &strKey, const std::string &strVal)
Set GUI look and feel value.
int getBttnMenuIdx(AlignOp eAlign)
Get button menu index from alignment enum.
MapLookFeel_T m_mapLookFeel
look and feel map
GtkWidget * m_wCvImageBox[MaxCvImages]
CvImage box containers.
static void onRemoveWidget(GtkWidget *w, gpointer user_data)
Remove widget callback handler.
virtual bool addLabelButton(int nBttnId, AlignOp eAlign, const std::string &strLabel, const std::string &strToolTip="")
Add a button with a label to window button menu.
virtual bool addImageButton(int nBttnId, AlignOp eAlign, const std::string &strIconPath, const std::string &strAltText, const std::string &strToolTip="")
Add a button with an image to window button menu.
virtual void clearStatus()
Clear status message.
virtual void wait(int delay)
Wait for timeout.
GtkWidget * m_wWorkspace
middle workspace container widget
void convertLookAndFeelDefaults()
Convert Look and Feel defaults to native GTK/GDK values.
GtkWidget * m_wPageRef
workflow page reference
bool m_bMouseEvent
was a mouse event (click, drag, etc)
int m_nWinWidth
window width
void * m_dataBttnCb
registered menu button callback data
virtual void configureCvImage(uint_t uImgIndex)
Configure OpenCV image widget.
CvRect m_rectWorkspace
workspace bounding rectangle
virtual int waitKey(int delay)
Wait for keypress or timeout.
CvPoint m_ptCvImageOrig[MaxCvImages]
origin of shown CvImage
virtual void removeWorkspaceCvImageDisplay(uint_t uImgIndex)
Remove OpenCV display widget from workspace.
GtkWidget * m_wStatusBar
status message bar
virtual void showStatus(const char *sFmt,...)
Show status message.
GtkWidget * m_wExtraVBox
extra vertical box