Commit 900e1dcd authored by Jean-Paul Saman's avatar Jean-Paul Saman

Refactor toolbar sizing.

parent 03a19fdb
...@@ -44,10 +44,7 @@ VlcPlugin::VlcPlugin( NPP instance, uint16 mode ) : ...@@ -44,10 +44,7 @@ VlcPlugin::VlcPlugin( NPP instance, uint16 mode ) :
i_npmode(mode), i_npmode(mode),
b_stream(0), b_stream(0),
b_autoplay(1), b_autoplay(1),
b_show_toolbar(1), b_toolbar(0),
#if XP_UNIX
i_control_height(45),
#endif
psz_target(NULL), psz_target(NULL),
libvlc_instance(NULL), libvlc_instance(NULL),
libvlc_log(NULL), libvlc_log(NULL),
...@@ -60,6 +57,8 @@ VlcPlugin::VlcPlugin( NPP instance, uint16 mode ) : ...@@ -60,6 +57,8 @@ VlcPlugin::VlcPlugin( NPP instance, uint16 mode ) :
#if XP_UNIX #if XP_UNIX
,i_width((unsigned)-1) ,i_width((unsigned)-1)
,i_height((unsigned)-1) ,i_height((unsigned)-1)
,i_tb_width(0)
,i_tb_height(0)
,i_last_position(0) ,i_last_position(0)
#endif #endif
{ {
...@@ -167,9 +166,9 @@ NPError VlcPlugin::init(int argc, char* const argn[], char* const argv[]) ...@@ -167,9 +166,9 @@ NPError VlcPlugin::init(int argc, char* const argn[], char* const argv[])
{ {
progid = argv[i]; progid = argv[i];
} }
else if( !strcmp( argn[i], "show_toolbar" ) ) else if( !strcmp( argn[i], "toolbar" ) )
{ {
b_show_toolbar = boolValue(argv[i]); b_toolbar = boolValue(argv[i]);
} }
} }
...@@ -459,47 +458,66 @@ void VlcPlugin::showToolbar() ...@@ -459,47 +458,66 @@ void VlcPlugin::showToolbar()
const NPWindow& window = getWindow(); const NPWindow& window = getWindow();
Window control = getControlWindow(); Window control = getControlWindow();
Display *p_display = ((NPSetWindowCallbackStruct *)window.ws_info)->display; Display *p_display = ((NPSetWindowCallbackStruct *)window.ws_info)->display;
unsigned int i_height = 0, i_width = 0;
/* load icons */ /* load icons */
XpmReadFileToImage( p_display, DATA_PATH "/mozilla/play.xpm", XpmReadFileToImage( p_display, DATA_PATH "/mozilla/play.xpm",
&p_btnPlay, NULL, NULL); &p_btnPlay, NULL, NULL);
if( p_btnPlay ) if( p_btnPlay )
i_control_height = __MAX( i_control_height, p_btnPlay->height ); {
i_height = __MAX( i_height, p_btnPlay->height );
i_width = __MAX( i_width, p_btnPlay->width );
}
XpmReadFileToImage( p_display, DATA_PATH "/mozilla/pause.xpm", XpmReadFileToImage( p_display, DATA_PATH "/mozilla/pause.xpm",
&p_btnPause, NULL, NULL); &p_btnPause, NULL, NULL);
if( p_btnPause ) if( p_btnPause )
i_control_height = __MAX( i_control_height, p_btnPause->height ); {
i_height = __MAX( i_height, p_btnPause->height );
i_width = __MAX( i_width, p_btnPause->width );
}
XpmReadFileToImage( p_display, DATA_PATH "/mozilla/stop.xpm", XpmReadFileToImage( p_display, DATA_PATH "/mozilla/stop.xpm",
&p_btnStop, NULL, NULL ); &p_btnStop, NULL, NULL );
if( p_btnStop ) if( p_btnStop )
i_control_height = __MAX( i_control_height, p_btnStop->height ); {
i_height = __MAX( i_height, p_btnStop->height );
i_width = __MAX( i_width, p_btnStop->width );
}
XpmReadFileToImage( p_display, DATA_PATH "/mozilla/time_line.xpm", XpmReadFileToImage( p_display, DATA_PATH "/mozilla/time_line.xpm",
&p_timeline, NULL, NULL); &p_timeline, NULL, NULL);
if( p_timeline ) if( p_timeline )
i_control_height = __MAX( i_control_height, p_timeline->height ); {
i_height = __MAX( i_height, p_timeline->height );
i_width = __MAX( i_width, p_timeline->width );
}
XpmReadFileToImage( p_display, DATA_PATH "/mozilla/time_icon.xpm", XpmReadFileToImage( p_display, DATA_PATH "/mozilla/time_icon.xpm",
&p_btnTime, NULL, NULL); &p_btnTime, NULL, NULL);
if( p_btnTime ) if( p_btnTime )
i_control_height = __MAX( i_control_height, p_btnTime->height ); {
i_height = __MAX( i_height, p_btnTime->height );
i_width = __MAX( i_width, p_btnTime->width );
}
XpmReadFileToImage( p_display, DATA_PATH "/mozilla/fullscreen.xpm", XpmReadFileToImage( p_display, DATA_PATH "/mozilla/fullscreen.xpm",
&p_btnFullscreen, NULL, NULL); &p_btnFullscreen, NULL, NULL);
if( p_btnFullscreen ) if( p_btnFullscreen )
i_control_height = __MAX( i_control_height, p_btnFullscreen->height); {
i_height = __MAX( i_height, p_btnFullscreen->height );
i_width = __MAX( i_width, p_btnFullscreen->width );
}
XpmReadFileToImage( p_display, DATA_PATH "/mozilla/volume_max.xpm", XpmReadFileToImage( p_display, DATA_PATH "/mozilla/volume_max.xpm",
&p_btnMute, NULL, NULL); &p_btnMute, NULL, NULL);
if( p_btnMute ) if( p_btnMute )
i_control_height = __MAX( i_control_height, p_btnMute->height); {
i_height = __MAX( i_height, p_btnMute->height );
i_width = __MAX( i_width, p_btnMute->width );
}
XpmReadFileToImage( p_display, DATA_PATH "/mozilla/volume_mute.xpm", XpmReadFileToImage( p_display, DATA_PATH "/mozilla/volume_mute.xpm",
&p_btnUnmute, NULL, NULL); &p_btnUnmute, NULL, NULL);
if( p_btnUnmute ) if( p_btnUnmute )
i_control_height = __MAX( i_control_height, p_btnUnmute->height); {
i_height = __MAX( i_height, p_btnUnmute->height );
i_width = __MAX( i_width, p_btnUnmute->width );
}
setToolbarSize( i_width, i_height );
if( !p_btnPlay || !p_btnPause || !p_btnStop || !p_timeline || if( !p_btnPlay || !p_btnPause || !p_btnStop || !p_timeline ||
!p_btnTime || !p_btnFullscreen || !p_btnMute || !p_btnUnmute ) !p_btnTime || !p_btnFullscreen || !p_btnMute || !p_btnUnmute )
...@@ -508,6 +526,8 @@ void VlcPlugin::showToolbar() ...@@ -508,6 +526,8 @@ void VlcPlugin::showToolbar()
void VlcPlugin::hideToolbar() void VlcPlugin::hideToolbar()
{ {
i_tb_width = i_tb_height = 0;
if( p_btnPlay ) XDestroyImage( p_btnPlay ); if( p_btnPlay ) XDestroyImage( p_btnPlay );
if( p_btnPause ) XDestroyImage( p_btnPause ); if( p_btnPause ) XDestroyImage( p_btnPause );
if( p_btnStop ) XDestroyImage( p_btnStop ); if( p_btnStop ) XDestroyImage( p_btnStop );
...@@ -534,9 +554,10 @@ void VlcPlugin::redrawToolbar() ...@@ -534,9 +554,10 @@ void VlcPlugin::redrawToolbar()
float f_position = 0.0; float f_position = 0.0;
int i_playing = 0; int i_playing = 0;
bool b_mute = false; bool b_mute = false;
unsigned int dst_x, dst_y;
GC gc; GC gc;
XGCValues gcv; XGCValues gcv;
#define BTN_SPACE ((unsigned int)4)
const NPWindow& window = getWindow(); const NPWindow& window = getWindow();
Window control = getControlWindow(); Window control = getControlWindow();
...@@ -570,50 +591,69 @@ void VlcPlugin::redrawToolbar() ...@@ -570,50 +591,69 @@ void VlcPlugin::redrawToolbar()
gc = XCreateGC( p_display, control, GCForeground, &gcv ); gc = XCreateGC( p_display, control, GCForeground, &gcv );
XFillRectangle( p_display, control, gc, XFillRectangle( p_display, control, gc,
0, 0, window.width, i_control_height ); 0, 0, window.width, i_tb_height );
gcv.foreground = WhitePixel( p_display, 0 ); gcv.foreground = WhitePixel( p_display, 0 );
XChangeGC( p_display, gc, GCForeground, &gcv ); XChangeGC( p_display, gc, GCForeground, &gcv );
/* position icons */ /* position icons */
dst_x = 4; dst_y = 4;
fprintf( stderr, ">>>>>> is playing = %d\n", i_playing ); fprintf( stderr, ">>>>>> is playing = %d\n", i_playing );
if( p_btnPause && (i_playing == 1) ) if( p_btnPause && (i_playing == 1) )
{ {
XPutImage( p_display, control, gc, p_btnPause, 0, 0, 4, 14, XPutImage( p_display, control, gc, p_btnPause, 0, 0, dst_x, dst_y,
p_btnPause->width, p_btnPause->height ); p_btnPause->width, p_btnPause->height );
} }
else if( p_btnPlay ) else if( p_btnPlay )
{ {
XPutImage( p_display, control, gc, p_btnPlay, 0, 0, 4, 14, XPutImage( p_display, control, gc, p_btnPlay, 0, 0, dst_x, dst_y,
p_btnPlay->width, p_btnPlay->height ); p_btnPlay->width, p_btnPlay->height );
} }
dst_x += BTN_SPACE + ( p_btnPlay ? p_btnPlay->width : 0 );
dst_y = 4;
if( p_btnStop ) if( p_btnStop )
XPutImage( p_display, control, gc, p_btnStop, 0, 0, 39, 14, XPutImage( p_display, control, gc, p_btnStop, 0, 0, dst_x, dst_y,
p_btnStop->width, p_btnStop->height ); p_btnStop->width, p_btnStop->height );
dst_x += BTN_SPACE + ( p_btnStop ? p_btnStop->width : 0 );
dst_y = 4;
if( p_btnFullscreen ) if( p_btnFullscreen )
XPutImage( p_display, control, gc, p_btnFullscreen, 0, 0, 67, 21, XPutImage( p_display, control, gc, p_btnFullscreen, 0, 0, dst_x, dst_y,
p_btnFullscreen->width, p_btnFullscreen->height ); p_btnFullscreen->width, p_btnFullscreen->height );
dst_x += BTN_SPACE + ( p_btnFullscreen ? p_btnFullscreen->width : 0 );
dst_y = 4;
if( p_btnUnmute && b_mute ) if( p_btnUnmute && b_mute )
{ {
XPutImage( p_display, control, gc, p_btnUnmute, 0, 0, 94, 30, XPutImage( p_display, control, gc, p_btnUnmute, 0, 0, dst_x, dst_y,
p_btnUnmute->width, p_btnUnmute->height ); p_btnUnmute->width, p_btnUnmute->height );
dst_x += BTN_SPACE + ( p_btnUnmute ? p_btnUnmute->width : 0 );
dst_y = 4;
} }
else if( p_btnMute ) else if( p_btnMute )
{ {
XPutImage( p_display, control, gc, p_btnMute, 0, 0, 94, 30, XPutImage( p_display, control, gc, p_btnMute, 0, 0, dst_x, dst_y,
p_btnMute->width, p_btnMute->height ); p_btnMute->width, p_btnMute->height );
dst_x += BTN_SPACE + ( p_btnMute ? p_btnMute->width : 0 );
dst_y = 4;
} }
if( p_timeline ) if( p_timeline )
XPutImage( p_display, control, gc, p_timeline, 0, 0, 4, 4, XPutImage( p_display, control, gc, p_timeline, 0, 0, dst_x, dst_y,
(window.width-8), p_timeline->height ); (window.width-(dst_x+BTN_SPACE)), p_timeline->height );
if( f_position > 0 ) if( f_position > 0 )
i_last_position = (((float)window.width-8.0)/100.0)*f_position; i_last_position = (((float)window.width-8.0)/100.0)*f_position;
if( p_btnTime ) if( p_btnTime )
XPutImage( p_display, control, gc, p_btnTime, XPutImage( p_display, control, gc, p_btnTime,
0, 0, (4+i_last_position), 2, 0, 0, (dst_x+i_last_position), dst_y,
p_btnTime->width, p_btnTime->height ); p_btnTime->width, p_btnTime->height );
XFreeGC( p_display, gc ); XFreeGC( p_display, gc );
......
...@@ -111,6 +111,10 @@ public: ...@@ -111,6 +111,10 @@ public:
void showToolbar(); void showToolbar();
void hideToolbar(); void hideToolbar();
void redrawToolbar(); void redrawToolbar();
void getToolbarSize(unsigned int *width, unsigned int *height)
{ *width = i_tb_width; *height = i_tb_height; };
int setToolbarSize(unsigned int width, unsigned int height)
{ i_tb_width = width; i_tb_height = height; return 1; };
#endif #endif
uint16 i_npmode; /* either NP_EMBED or NP_FULL */ uint16 i_npmode; /* either NP_EMBED or NP_FULL */
...@@ -118,13 +122,9 @@ public: ...@@ -118,13 +122,9 @@ public:
/* plugin properties */ /* plugin properties */
int b_stream; int b_stream;
int b_autoplay; int b_autoplay;
int b_show_toolbar; int b_toolbar;
char * psz_target; char * psz_target;
#if XP_UNIX
/* toolbar */
int i_control_height;
#endif
private: private:
/* VLC reference */ /* VLC reference */
libvlc_instance_t *libvlc_instance; libvlc_instance_t *libvlc_instance;
...@@ -142,6 +142,7 @@ private: ...@@ -142,6 +142,7 @@ private:
#endif #endif
#if XP_UNIX #if XP_UNIX
unsigned int i_width, i_height; unsigned int i_width, i_height;
unsigned int i_tb_width, i_tb_height;
Window npvideo, npcontrol; Window npvideo, npcontrol;
XImage *p_btnPlay; XImage *p_btnPlay;
......
...@@ -364,8 +364,8 @@ NPError NPP_Destroy( NPP instance, NPSavedData** save ) ...@@ -364,8 +364,8 @@ NPError NPP_Destroy( NPP instance, NPSavedData** save )
NPError NPP_SetWindow( NPP instance, NPWindow* window ) NPError NPP_SetWindow( NPP instance, NPWindow* window )
{ {
/* height used by bottom toolbar (pixels). 0 if hidden */ Window control;
unsigned int i_toolbar_height; unsigned int i_control_height = 0, i_control_width = 0;
if( ! instance ) if( ! instance )
{ {
...@@ -379,19 +379,10 @@ NPError NPP_SetWindow( NPP instance, NPWindow* window ) ...@@ -379,19 +379,10 @@ NPError NPP_SetWindow( NPP instance, NPWindow* window )
/* we should probably show a splash screen here */ /* we should probably show a splash screen here */
return NPERR_NO_ERROR; return NPERR_NO_ERROR;
} }
control = p_plugin->getControlWindow();
libvlc_instance_t *p_vlc = p_plugin->getVLC(); libvlc_instance_t *p_vlc = p_plugin->getVLC();
if( p_plugin->b_show_toolbar )
{
i_toolbar_height = p_plugin->i_control_height;
}
else
{
i_toolbar_height = 0;
}
/* /*
* PLUGIN DEVELOPERS: * PLUGIN DEVELOPERS:
* Before setting window to point to the * Before setting window to point to the
...@@ -496,6 +487,15 @@ NPError NPP_SetWindow( NPP instance, NPWindow* window ) ...@@ -496,6 +487,15 @@ NPError NPP_SetWindow( NPP instance, NPWindow* window )
#endif /* XP_WIN */ #endif /* XP_WIN */
#ifdef XP_UNIX #ifdef XP_UNIX
if( p_plugin->b_toolbar )
{
p_plugin->getToolbarSize( &i_control_width, &i_control_height );
}
else
{
i_control_height = i_control_width = 0;
}
if( window && window->window ) if( window && window->window )
{ {
Window parent = (Window) window->window; Window parent = (Window) window->window;
...@@ -510,14 +510,14 @@ NPError NPP_SetWindow( NPP instance, NPWindow* window ) ...@@ -510,14 +510,14 @@ NPError NPP_SetWindow( NPP instance, NPWindow* window )
/* create windows */ /* create windows */
Window video = XCreateSimpleWindow( p_display, parent, 0, 0, Window video = XCreateSimpleWindow( p_display, parent, 0, 0,
window->width, window->height - i_toolbar_height, window->width, window->height - i_control_height,
0, i_blackColor, i_blackColor ); 0, i_blackColor, i_blackColor );
Window controls = (Window) NULL; Window controls = (Window) NULL;
if( p_plugin->b_show_toolbar ) if( p_plugin->b_toolbar )
{ {
controls = XCreateSimpleWindow( p_display, parent, controls = XCreateSimpleWindow( p_display, parent,
0, window->height - i_toolbar_height-1, 0, window->height - i_control_height-1,
window->width, i_toolbar_height-1, window->width, i_control_height-1,
0, i_blackColor, i_blackColor ); 0, i_blackColor, i_blackColor );
} }
...@@ -790,21 +790,19 @@ static LRESULT CALLBACK Manage( HWND p_hwnd, UINT i_msg, WPARAM wpar, LPARAM lpa ...@@ -790,21 +790,19 @@ static LRESULT CALLBACK Manage( HWND p_hwnd, UINT i_msg, WPARAM wpar, LPARAM lpa
static void Redraw( Widget w, XtPointer closure, XEvent *event ) static void Redraw( Widget w, XtPointer closure, XEvent *event )
{ {
VlcPlugin* p_plugin = reinterpret_cast<VlcPlugin*>(closure); VlcPlugin* p_plugin = reinterpret_cast<VlcPlugin*>(closure);
Window control = p_plugin->getControlWindow();
const NPWindow& window = p_plugin->getWindow(); const NPWindow& window = p_plugin->getWindow();
GC gc; GC gc;
XGCValues gcv; XGCValues gcv;
/* height used to show the bottom toolbar in non-fullscreen mode */ unsigned int i_control_height, i_control_width;
unsigned int i_toolbar_height;
if( p_plugin->b_show_toolbar ) if( p_plugin->b_toolbar )
{ {
p_plugin->showToolbar(); p_plugin->showToolbar();
i_toolbar_height = p_plugin->i_control_height; p_plugin->getToolbarSize( &i_control_width, &i_control_height );
} }
else else
{ i_control_height = i_control_width = 0;
i_toolbar_height = 0;
}
Window video = p_plugin->getVideoWindow(); Window video = p_plugin->getVideoWindow();
Display *p_display = ((NPSetWindowCallbackStruct *)window.ws_info)->display; Display *p_display = ((NPSetWindowCallbackStruct *)window.ws_info)->display;
...@@ -813,17 +811,17 @@ static void Redraw( Widget w, XtPointer closure, XEvent *event ) ...@@ -813,17 +811,17 @@ static void Redraw( Widget w, XtPointer closure, XEvent *event )
gc = XCreateGC( p_display, video, GCForeground, &gcv ); gc = XCreateGC( p_display, video, GCForeground, &gcv );
XFillRectangle( p_display, video, gc, XFillRectangle( p_display, video, gc,
0, 0, window.width, window.height - i_toolbar_height); 0, 0, window.width, window.height - i_control_height);
gcv.foreground = WhitePixel( p_display, 0 ); gcv.foreground = WhitePixel( p_display, 0 );
XChangeGC( p_display, gc, GCForeground, &gcv ); XChangeGC( p_display, gc, GCForeground, &gcv );
XDrawString( p_display, video, gc, XDrawString( p_display, video, gc,
window.width / 2 - 40, (window.height - i_toolbar_height) / 2, window.width / 2 - 40, (window.height - i_control_height) / 2,
WINDOW_TEXT, strlen(WINDOW_TEXT) ); WINDOW_TEXT, strlen(WINDOW_TEXT) );
XFreeGC( p_display, gc ); XFreeGC( p_display, gc );
if( p_plugin->b_show_toolbar ) if( p_plugin->b_toolbar )
{ {
p_plugin->redrawToolbar(); p_plugin->redrawToolbar();
p_plugin->hideToolbar(); p_plugin->hideToolbar();
...@@ -840,7 +838,7 @@ static void ControlHandler( Widget w, XtPointer closure, XEvent *event ) ...@@ -840,7 +838,7 @@ static void ControlHandler( Widget w, XtPointer closure, XEvent *event )
int i_xPos = event->xbutton.x; int i_xPos = event->xbutton.x;
int i_yPos = event->xbutton.y; int i_yPos = event->xbutton.y;
if( p_plugin && p_plugin->b_show_toolbar ) if( p_plugin && p_plugin->b_toolbar )
{ {
libvlc_exception_t ex; libvlc_exception_t ex;
libvlc_exception_init( &ex ); libvlc_exception_init( &ex );
...@@ -924,6 +922,7 @@ static void ControlHandler( Widget w, XtPointer closure, XEvent *event ) ...@@ -924,6 +922,7 @@ static void ControlHandler( Widget w, XtPointer closure, XEvent *event )
static void Resize ( Widget w, XtPointer closure, XEvent *event ) static void Resize ( Widget w, XtPointer closure, XEvent *event )
{ {
VlcPlugin* p_plugin = reinterpret_cast<VlcPlugin*>(closure); VlcPlugin* p_plugin = reinterpret_cast<VlcPlugin*>(closure);
Window control = p_plugin->getControlWindow();
const NPWindow& window = p_plugin->getWindow(); const NPWindow& window = p_plugin->getWindow();
Window drawable = p_plugin->getVideoWindow(); Window drawable = p_plugin->getVideoWindow();
Display *p_display = ((NPSetWindowCallbackStruct *)window.ws_info)->display; Display *p_display = ((NPSetWindowCallbackStruct *)window.ws_info)->display;
...@@ -932,16 +931,15 @@ static void Resize ( Widget w, XtPointer closure, XEvent *event ) ...@@ -932,16 +931,15 @@ static void Resize ( Widget w, XtPointer closure, XEvent *event )
Window root_return, parent_return, * children_return; Window root_return, parent_return, * children_return;
Window base_window; Window base_window;
unsigned int i_nchildren; unsigned int i_nchildren;
/* height used for the bottom control bar, 0 if hidden */ unsigned int i_control_height, i_control_width;
unsigned int i_toolbar_height;
if( p_plugin->b_show_toolbar ) if( p_plugin->b_toolbar )
{ {
i_toolbar_height = p_plugin->i_control_height; p_plugin->getToolbarSize( &i_control_width, &i_control_height );
} }
else else
{ {
i_toolbar_height = 0; i_control_height = i_control_width = 0;
} }
#ifdef X11_RESIZE_DEBUG #ifdef X11_RESIZE_DEBUG
...@@ -956,14 +954,14 @@ static void Resize ( Widget w, XtPointer closure, XEvent *event ) ...@@ -956,14 +954,14 @@ static void Resize ( Widget w, XtPointer closure, XEvent *event )
} }
#endif /* X11_RESIZE_DEBUG */ #endif /* X11_RESIZE_DEBUG */
if( ! p_plugin->setSize(window.width, (window.height - i_toolbar_height)) ) if( ! p_plugin->setSize(window.width, (window.height - i_control_height)) )
{ {
/* size already set */ /* size already set */
return; return;
} }
i_ret = XResizeWindow( p_display, drawable, i_ret = XResizeWindow( p_display, drawable,
window.width, (window.height - i_toolbar_height) ); window.width, (window.height - i_control_height) );
#ifdef X11_RESIZE_DEBUG #ifdef X11_RESIZE_DEBUG
fprintf( stderr, fprintf( stderr,
...@@ -995,7 +993,7 @@ static void Resize ( Widget w, XtPointer closure, XEvent *event ) ...@@ -995,7 +993,7 @@ static void Resize ( Widget w, XtPointer closure, XEvent *event )
#endif /* X11_RESIZE_DEBUG */ #endif /* X11_RESIZE_DEBUG */
i_ret = XResizeWindow( p_display, base_window, i_ret = XResizeWindow( p_display, base_window,
window.width, ( window.height - i_toolbar_height ) ); window.width, ( window.height - i_control_height ) );
#ifdef X11_RESIZE_DEBUG #ifdef X11_RESIZE_DEBUG
fprintf( stderr, fprintf( stderr,
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment