示例#1
0
static int iMatrixSetFitToSizeAttrib(Ihandle* ih, const char* value)
{
  int w, h;
  int sb_w = 0, sb_h = 0;

  if (!ih->handle)
    ih->data->canvas.sb = iupBaseGetScrollbar(ih);

  /* add scrollbar */
  if (ih->data->canvas.sb)
  {
    int sb_size = iupdrvGetScrollbarSize();
    if (ih->data->canvas.sb & IUP_SB_HORIZ)
      sb_h += sb_size;  /* sb horizontal affects vertical size */
    if (ih->data->canvas.sb & IUP_SB_VERT)
      sb_w += sb_size;  /* sb vertical affects horizontal size */
  }

  IupGetIntInt(ih, "RASTERSIZE", &w, &h);

  if (iupStrEqualNoCase(value, "LINES"))
    iMatrixFitLines(ih, h-sb_h);
  else if (iupStrEqualNoCase(value, "COLUMNS"))
    iMatrixFitColumns(ih, w-sb_w);
  else
  {
    iMatrixFitLines(ih, h-sb_h);
    iMatrixFitColumns(ih, w-sb_w);
  }

  ih->data->need_calcsize = 1;
  if (ih->handle)
    iupMatrixDraw(ih, 1);
  return 0;
}
示例#2
0
static void iMatrixComputeNaturalSizeMethod(Ihandle* ih, int *w, int *h, int *expand)
{
  int natural_w = 0, natural_h = 0;
  (void)expand; /* unset if not a container */

  if (!ih->handle)
    ih->data->canvas.sb = iupBaseGetScrollbar(ih);

  /* add scrollbar */
  if (ih->data->canvas.sb)
  {
    int sb_size = iupdrvGetScrollbarSize();
    if (ih->data->canvas.sb & IUP_SB_HORIZ)
      natural_h += sb_size;  /* sb horizontal affects vertical size */
    if (ih->data->canvas.sb & IUP_SB_VERT)
      natural_w += sb_size;  /* sb vertical affects horizontal size */
  }

  *w = natural_w + iMatrixGetNaturalWidth(ih);
  *h = natural_h + iMatrixGetNaturalHeight(ih);
}
示例#3
0
static int gtkCanvasMapMethod(Ihandle* ih)
{
  GtkWidget* sb_win;
#if !GTK_CHECK_VERSION(3, 0, 0)
  void* visual;
#endif

  if (!ih->parent)
    return IUP_ERROR;

  ih->data->sb = iupBaseGetScrollbar(ih);

#if !GTK_CHECK_VERSION(3, 0, 0)
  visual = (void*)IupGetAttribute(ih, "VISUAL");   /* defined by the OpenGL Canvas in X11 or NULL */
  if (visual)
    iupgtkPushVisualAndColormap(visual, (void*)iupAttribGet(ih, "COLORMAP"));
#endif

  ih->handle = iupgtkNativeContainerNew();  /* canvas is also a container */

#if !GTK_CHECK_VERSION(3, 0, 0)
  if (visual)
    gtk_widget_pop_colormap();
#endif

  if (!ih->handle)
      return IUP_ERROR;

  /* CD will NOT work properly without this, must use always the CD-GDK driver */
  iupgtkNativeContainerSetHasWindow(ih->handle, TRUE);  

  sb_win = iupgtkNativeContainerNew();
  if (!sb_win)
    return IUP_ERROR;

  iupgtkNativeContainerAdd(sb_win, ih->handle);
  gtk_widget_show(sb_win);

  iupAttribSetStr(ih, "_IUP_EXTRAPARENT", (char*)sb_win);

  /* add to the parent, all GTK controls must call this. */
  iupgtkAddToParent(ih);

  g_signal_connect(G_OBJECT(ih->handle), "focus-in-event",     G_CALLBACK(iupgtkFocusInOutEvent), ih);
  g_signal_connect(G_OBJECT(ih->handle), "focus-out-event",    G_CALLBACK(iupgtkFocusInOutEvent), ih);
  g_signal_connect(G_OBJECT(ih->handle), "key-press-event",    G_CALLBACK(iupgtkKeyPressEvent), ih);
  g_signal_connect(G_OBJECT(ih->handle), "key-release-event",  G_CALLBACK(iupgtkKeyReleaseEvent), ih);
  g_signal_connect(G_OBJECT(ih->handle), "enter-notify-event", G_CALLBACK(iupgtkEnterLeaveEvent), ih);
  g_signal_connect(G_OBJECT(ih->handle), "leave-notify-event", G_CALLBACK(iupgtkEnterLeaveEvent), ih);
  g_signal_connect(G_OBJECT(ih->handle), "show-help",          G_CALLBACK(iupgtkShowHelp), ih);

#if GTK_CHECK_VERSION(3, 0, 0)
  g_signal_connect(G_OBJECT(ih->handle), "draw",               G_CALLBACK(gtkCanvasDraw), ih);
#else
  g_signal_connect(G_OBJECT(ih->handle), "expose-event",       G_CALLBACK(gtkCanvasExposeEvent), ih);
#endif
  g_signal_connect(G_OBJECT(ih->handle), "button-press-event", G_CALLBACK(gtkCanvasButtonEvent), ih);
  g_signal_connect(G_OBJECT(ih->handle), "button-release-event",G_CALLBACK(gtkCanvasButtonEvent), ih);
  g_signal_connect(G_OBJECT(ih->handle), "motion-notify-event",G_CALLBACK(iupgtkMotionNotifyEvent), ih);
  g_signal_connect(G_OBJECT(ih->handle), "scroll-event",G_CALLBACK(gtkCanvasScrollEvent), ih);

  g_signal_connect(G_OBJECT(ih->handle), "size-allocate", G_CALLBACK(gtkCanvasSizeAllocate), ih);

  /* To receive mouse events on a drawing area, you will need to enable them. */
  gtk_widget_add_events(ih->handle, GDK_EXPOSURE_MASK|
    GDK_POINTER_MOTION_MASK|GDK_POINTER_MOTION_HINT_MASK|
    GDK_BUTTON_PRESS_MASK|GDK_BUTTON_RELEASE_MASK|GDK_BUTTON_MOTION_MASK|
    GDK_KEY_PRESS_MASK|GDK_KEY_RELEASE_MASK|
    GDK_ENTER_NOTIFY_MASK|GDK_LEAVE_NOTIFY_MASK|
    GDK_FOCUS_CHANGE_MASK|GDK_STRUCTURE_MASK);

  /* To receive keyboard events, you will need to set the GTK_CAN_FOCUS flag on the drawing area. */
  if (ih->iclass->is_interactive)
  {
    if (iupAttribGetBoolean(ih, "CANFOCUS"))
      iupgtkSetCanFocus(ih->handle, 1);
  }

  if (iupAttribGetBoolean(ih, "BORDER"))
  {
    iupAttribSetInt(ih, "BORDERWIDTH", 1);
#if GTK_CHECK_VERSION(3, 0, 0)
    g_signal_connect(G_OBJECT(sb_win), "draw", G_CALLBACK(gtkCanvasBorderDraw), NULL);
#else
    g_signal_connect(G_OBJECT(sb_win), "expose-event", G_CALLBACK(gtkCanvasBorderExposeEvent), NULL);
#endif
  }

  gtk_widget_realize(sb_win);

  if (ih->data->sb & IUP_SB_HORIZ)
  {
#if GTK_CHECK_VERSION(3, 0, 0)
    GtkWidget* sb_horiz = gtk_scrollbar_new(GTK_ORIENTATION_HORIZONTAL, NULL);
#else
    GtkWidget* sb_horiz = gtk_hscrollbar_new(NULL);
#endif
    iupgtkNativeContainerAdd(sb_win, sb_horiz);
    gtk_widget_show(sb_horiz);
    gtk_widget_realize(sb_horiz);

    g_signal_connect(G_OBJECT(sb_horiz), "change-value",G_CALLBACK(gtkCanvasScrollHorizChangeValue), ih);
    g_signal_connect(G_OBJECT(gtk_range_get_adjustment(GTK_RANGE(sb_horiz))), "value-changed",G_CALLBACK(gtkCanvasAdjustHorizValueChanged), ih);

    iupAttribSetStr(ih, "_IUPGTK_SBHORIZ", (char*)sb_horiz);
  }

  if (ih->data->sb & IUP_SB_VERT)
  {
#if GTK_CHECK_VERSION(3, 0, 0)
    GtkWidget* sb_vert = gtk_scrollbar_new(GTK_ORIENTATION_VERTICAL, NULL);
#else
    GtkWidget* sb_vert = gtk_vscrollbar_new(NULL);
#endif
    iupgtkNativeContainerAdd(sb_win, sb_vert);
    gtk_widget_show(sb_vert);
    gtk_widget_realize(sb_vert);

    g_signal_connect(G_OBJECT(sb_vert), "change-value",G_CALLBACK(gtkCanvasScrollVertChangeValue), ih);
    g_signal_connect(G_OBJECT(gtk_range_get_adjustment(GTK_RANGE(sb_vert))), "value-changed",G_CALLBACK(gtkCanvasAdjustVertValueChanged), ih);
    iupAttribSetStr(ih, "_IUPGTK_SBVERT", (char*)sb_vert);
  }

  gtk_widget_realize(ih->handle);

  /* configure for DRAG&DROP */
  if (IupGetCallback(ih, "DROPFILES_CB"))
    iupAttribSetStr(ih, "DROPFILESTARGET", "YES");

  /* update a mnemonic in a label if necessary */
  iupgtkUpdateMnemonic(ih);

  /* force the update of BGCOLOR here, to let derived classes ignore it if ACTION is defined */
  gtkCanvasSetBgColorAttrib(ih, iupAttribGetStr(ih, "BGCOLOR"));
    
  return IUP_NOERROR;
}
示例#4
0
static int winCanvasMapMethod(Ihandle* ih)
{
  CLIENTCREATESTRUCT clientstruct;
  void *clientdata = NULL;
  char *classname;
  DWORD dwStyle = WS_CHILD|WS_CLIPSIBLINGS, 
      dwExStyle = 0;

  if (!ih->parent)
    return IUP_ERROR;

  if (ih->iclass->is_interactive)
  {
    if (iupAttribGetBoolean(ih, "CANFOCUS"))
      dwStyle |= WS_TABSTOP;
  }
                           
  if (ih->firstchild) /* can be a container */
    iupwinGetNativeParentStyle(ih, &dwExStyle, &dwStyle);

  if (iupAttribGetBoolean(ih, "BORDER"))
    dwStyle |= WS_BORDER;

  ih->data->sb = iupBaseGetScrollbar(ih);
  if (ih->data->sb & IUP_SB_HORIZ)
    dwStyle |= WS_HSCROLL;
  if (ih->data->sb & IUP_SB_VERT)
    dwStyle |= WS_VSCROLL;
                           
  if (iupAttribGetBoolean(ih, "MDICLIENT"))  
  {
    /* creating a MDI Client that will be inside the MDI Frame, 
       it will work as parent of all MDI children */
    Ihandle *winmenu = IupGetAttributeHandle(ih, "MDIMENU");

    classname = "mdiclient";
    dwStyle = WS_CHILD|WS_CLIPCHILDREN|WS_VSCROLL|WS_HSCROLL|MDIS_ALLCHILDSTYLES;
    dwExStyle = WS_EX_CLIENTEDGE;

    iupAttribSetStr(ih, "BORDER", "NO");

    iupAttribSetStr(IupGetDialog(ih), "MDICLIENT_HANDLE", (char*)ih);

    clientdata = &clientstruct;
    clientstruct.hWindowMenu = winmenu? winmenu->handle: NULL;

    /* The system increments the identifier 
       for each additional MDI child window the application creates, 
       and reassigns identifiers when the application 
       destroys a window to keep the range of identifiers contiguous. */
    clientstruct.idFirstChild = IUP_MDI_FIRSTCHILD;
  }
  else 
    classname = "IupCanvas";

  ih->serial = iupDialogGetChildId(ih);

  ih->handle = CreateWindowEx(dwExStyle,/* extended style */
          classname,                    /* window class */
          NULL,                         /* title */
          dwStyle,                      /* window style */
          0,                            /* x-position */
          0,                            /* y-position */
          10,                           /* default width to avoid 0 */
          10,                           /* default height to avoid 0 */
          iupChildTreeGetNativeParentHandle(ih),     /* window parent */
          (HMENU)ih->serial,            /* child identifier */
          iupwin_hinstance,             /* instance of app. */
          clientdata);

  if (!ih->handle)
    return IUP_ERROR;

  /* associate HWND with Ihandle*, all Win32 controls must call this. */
  iupwinHandleAdd(ih, ih->handle);

  if (iupAttribGetBoolean(ih, "MDICLIENT"))  
    iupwinChangeProc(ih, iupwinBaseWinProc);
  else
    IupSetCallback(ih, "_IUPWIN_OLDPROC_CB", (Icallback)DefWindowProc);

  IupSetCallback(ih, "_IUPWIN_CTRLPROC_CB", (Icallback)winCanvasProc);

  /* configure for DROP of files */
  if (IupGetCallback(ih, "DROPFILES_CB"))
    iupAttribSetStr(ih, "DROPFILESTARGET", "YES");

  return IUP_NOERROR;
}
static int winCanvasMapMethod(Ihandle* ih)
{
  CLIENTCREATESTRUCT clientstruct;
  void *clientdata = NULL;
  TCHAR *classname;
  DWORD dwStyle = WS_CHILD|WS_CLIPSIBLINGS, 
      dwExStyle = 0;

  if (!ih->parent)
    return IUP_ERROR;

  if (ih->iclass->is_interactive)
  {
    if (iupAttribGetBoolean(ih, "CANFOCUS"))
      dwStyle |= WS_TABSTOP;
  }
                           
  if (ih->firstchild) /* can be a container */
    iupwinGetNativeParentStyle(ih, &dwExStyle, &dwStyle);

  if (iupAttribGetBoolean(ih, "BORDER"))
    dwStyle |= WS_BORDER;

  ih->data->sb = iupBaseGetScrollbar(ih);
  if (ih->data->sb & IUP_SB_HORIZ)
    dwStyle |= WS_HSCROLL;
  if (ih->data->sb & IUP_SB_VERT)
    dwStyle |= WS_VSCROLL;
                           
  if (iupAttribGetBoolean(ih, "MDICLIENT"))  
  {
    /* creating a MDI Client that will be inside the MDI Frame, 
       it will work as parent of all MDI children */
    Ihandle *winmenu = IupGetAttributeHandle(ih, "MDIMENU");

    classname = TEXT("mdiclient");
    dwStyle = WS_CHILD|WS_CLIPCHILDREN|WS_VSCROLL|WS_HSCROLL|MDIS_ALLCHILDSTYLES;
    dwExStyle = WS_EX_CLIENTEDGE;

    iupAttribSet(ih, "BORDER", "NO");

    iupAttribSet(IupGetDialog(ih), "MDICLIENT_HANDLE", (char*)ih);

    clientdata = &clientstruct;
    clientstruct.hWindowMenu = winmenu? winmenu->handle: NULL;

    /* The system increments the identifier 
       for each additional MDI child window the application creates, 
       and reassigns identifiers when the application 
       destroys a window to keep the range of identifiers contiguous. */
    clientstruct.idFirstChild = IUP_MDI_FIRSTCHILD;
  }
  else 
    classname = TEXT("IupCanvas");

  if (!iupwinCreateWindow(ih, classname, dwExStyle, dwStyle, clientdata))
    return IUP_ERROR;

  IupSetCallback(ih, "_IUPWIN_CTRLMSGPROC_CB", (Icallback)winCanvasMsgProc);

  /* configure for DROP of files */
  if (IupGetCallback(ih, "DROPFILES_CB"))
    iupAttribSet(ih, "DROPFILESTARGET", "YES");

  winCanvasSetDXAttrib(ih, NULL);
  winCanvasSetDYAttrib(ih, NULL);

  return IUP_NOERROR;
}
static int motCanvasMapMethod(Ihandle* ih)
{
  Widget sb_win;
  char *visual;
  int num_args = 0;
  Arg args[20];

  if (!ih->parent)
    return IUP_ERROR;

  ih->data->sb = iupBaseGetScrollbar(ih);

  /*********************/
  /* Create the parent */
  /*********************/

  iupMOT_SETARG(args, num_args, XmNmappedWhenManaged, False);  /* not visible when managed */
  iupMOT_SETARG(args, num_args, XmNshadowThickness, 0);
  iupMOT_SETARG(args, num_args, XmNmarginWidth, 0);
  iupMOT_SETARG(args, num_args, XmNmarginHeight, 0);
  iupMOT_SETARG(args, num_args, XmNwidth, 100);  /* set this to avoid size calculation problems */
  iupMOT_SETARG(args, num_args, XmNheight, 100);
  iupMOT_SETARG(args, num_args, XmNresizePolicy, XmRESIZE_NONE);
  iupMOT_SETARG(args, num_args, XmNnavigationType, XmTAB_GROUP);

  if (iupAttribGetBoolean(ih, "BORDER"))
  {
    iupMOT_SETARG(args, num_args, XmNborderWidth, 1);
    iupMOT_SETARG(args, num_args, XmNborderColor, iupmotColorGetPixelStr("0 0 0"));
  }
  else
    iupMOT_SETARG(args, num_args, XmNborderWidth, 0);
  
  sb_win = XtCreateManagedWidget(
    iupDialogGetChildIdStr(ih),  /* child identifier */
    xmBulletinBoardWidgetClass,     /* widget class */
    iupChildTreeGetNativeParentHandle(ih), /* widget parent */
    args, num_args);

  if (!sb_win)
    return IUP_ERROR;

  ih->serial = iupDialogGetChildId(ih); /* must be after using the string */

  /****************************/
  /* Create the drawing area  */
  /****************************/

  num_args = 0;
  iupMOT_SETARG(args, num_args, XmNmarginHeight, 0);  /* no shadow margins */
  iupMOT_SETARG(args, num_args, XmNmarginWidth, 0);  /* no shadow margins */
  iupMOT_SETARG(args, num_args, XmNshadowThickness, 0);
  iupMOT_SETARG(args, num_args, XmNresizePolicy, XmRESIZE_NONE); /* no automatic resize of children */
  if (ih->iclass->is_interactive)
  {
    iupMOT_SETARG(args, num_args, XmNnavigationType, XmTAB_GROUP); /* include in navigation */

    if (iupAttribGetBoolean(ih, "CANFOCUS"))
      iupMOT_SETARG(args, num_args, XmNtraversalOn, True);
    else
      iupMOT_SETARG(args, num_args, XmNtraversalOn, False);
  }
  else
  {
    iupMOT_SETARG(args, num_args, XmNnavigationType, XmNONE);
    iupMOT_SETARG(args, num_args, XmNtraversalOn, False);
  }

  iupMOT_SETARG(args, num_args, XmNx, 0);  /* x-position */
  iupMOT_SETARG(args, num_args, XmNy, 0);  /* y-position */
  iupMOT_SETARG(args, num_args, XmNwidth, 10);  /* default width to avoid 0 */
  iupMOT_SETARG(args, num_args, XmNheight, 10); /* default height to avoid 0 */

  visual = IupGetAttribute(ih, "VISUAL");   /* defined by the OpenGL Canvas or NULL */
  if (visual)
  {
    Colormap colormap = (Colormap)iupAttribGet(ih, "COLORMAP");
    if (colormap)
      iupMOT_SETARG(args, num_args, XmNcolormap,colormap);

    iupmotDialogSetVisual(ih, visual);
  }

  ih->handle = XtCreateManagedWidget(
    "draw_area",                 /* child identifier */
    xmDrawingAreaWidgetClass,    /* widget class */
    sb_win,                  /* widget parent */
    args, num_args);

  if (!ih->handle)
  {
    XtDestroyWidget(sb_win);
    return IUP_ERROR;
  }

  if (visual)
    iupmotDialogResetVisual(ih);

  iupAttribSet(ih, "_IUP_EXTRAPARENT", (char*)sb_win);

  {
    XSetWindowAttributes attrs;
    attrs.bit_gravity = ForgetGravity; /* For the DrawingArea widget gets Expose events when you resize it to be smaller. */

    if (iupAttribGetBoolean(ih, "BACKINGSTORE"))
      attrs.backing_store = WhenMapped;
    else
      attrs.backing_store = NotUseful;

    XChangeWindowAttributes(iupmot_display, XtWindow(ih->handle), CWBitGravity|CWBackingStore, &attrs);
  }

  if (ih->data->sb & IUP_SB_HORIZ)
  {
    Widget sb_horiz = XtVaCreateManagedWidget("sb_horiz",
      xmScrollBarWidgetClass, sb_win,
      XmNorientation, XmHORIZONTAL,
      XmNsliderMark, XmTHUMB_MARK,
      XmNuserData, ih,
      NULL);

    XtAddCallback(sb_horiz, XmNvalueChangedCallback, motCanvasScrollbarCallback, (void*)IUP_SBPOSH);
    XtAddCallback(sb_horiz, XmNdragCallback, motCanvasScrollbarCallback, (void*)IUP_SBDRAGH);
    XtAddCallback(sb_horiz, XmNdecrementCallback, motCanvasScrollbarCallback, (void*)IUP_SBLEFT);
    XtAddCallback(sb_horiz, XmNincrementCallback, motCanvasScrollbarCallback, (void*)IUP_SBRIGHT);
    XtAddCallback(sb_horiz, XmNpageDecrementCallback, motCanvasScrollbarCallback, (void*)IUP_SBPGLEFT);
    XtAddCallback(sb_horiz, XmNpageIncrementCallback, motCanvasScrollbarCallback, (void*)IUP_SBPGRIGHT);

    iupAttribSet(ih, "_IUPMOT_SBHORIZ", (char*)sb_horiz);
  }

  if (ih->data->sb & IUP_SB_VERT)
  {
    Widget sb_vert = XtVaCreateManagedWidget("sb_vert",
      xmScrollBarWidgetClass, sb_win,
      XmNorientation, XmVERTICAL,
      XmNsliderMark, XmTHUMB_MARK,
      XmNuserData, ih,
      NULL);

    XtAddCallback(sb_vert, XmNvalueChangedCallback, motCanvasScrollbarCallback, (void*)IUP_SBPOSV);
    XtAddCallback(sb_vert, XmNdragCallback, motCanvasScrollbarCallback, (void*)IUP_SBDRAGV);
    XtAddCallback(sb_vert, XmNdecrementCallback, motCanvasScrollbarCallback, (void*)IUP_SBUP);
    XtAddCallback(sb_vert, XmNincrementCallback, motCanvasScrollbarCallback, (void*)IUP_SBDN);
    XtAddCallback(sb_vert, XmNpageDecrementCallback, motCanvasScrollbarCallback, (void*)IUP_SBPGUP);
    XtAddCallback(sb_vert, XmNpageIncrementCallback, motCanvasScrollbarCallback, (void*)IUP_SBPGDN);

    iupAttribSet(ih, "_IUPMOT_SBVERT", (char*)sb_vert);
  }

  XtAddCallback(ih->handle, XmNhelpCallback, (XtCallbackProc)iupmotHelpCallback, (XtPointer)ih);
  XtAddCallback(ih->handle, XmNexposeCallback, (XtCallbackProc)motCanvasExposeCallback, (XtPointer)ih);
  XtAddCallback(ih->handle, XmNresizeCallback, (XtCallbackProc)motCanvasResizeCallback,  (XtPointer)ih);
  XtAddCallback(ih->handle, XmNinputCallback,  (XtCallbackProc)motCanvasInputCallback,   (XtPointer)ih);

  XtAddEventHandler(ih->handle, EnterWindowMask, False,(XtEventHandler)iupmotEnterLeaveWindowEvent, (XtPointer)ih);
  XtAddEventHandler(ih->handle, LeaveWindowMask, False,(XtEventHandler)iupmotEnterLeaveWindowEvent, (XtPointer)ih);

  XtAddEventHandler(ih->handle, FocusChangeMask, False,(XtEventHandler)iupmotFocusChangeEvent,        (XtPointer)ih);
  XtAddEventHandler(ih->handle, KeyPressMask,    False, (XtEventHandler)iupmotKeyPressEvent,    (XtPointer)ih);
  XtAddEventHandler(ih->handle, KeyReleaseMask,  False, (XtEventHandler)iupmotCanvasKeyReleaseEvent,  (XtPointer)ih);
  XtAddEventHandler(ih->handle, PointerMotionMask, False, (XtEventHandler)iupmotPointerMotionEvent, (XtPointer)ih);

  /* initialize the widget */
  XtRealizeWidget(sb_win);

  motCanvasSetDXAttrib(ih, NULL);
  motCanvasSetDYAttrib(ih, NULL);

  return IUP_NOERROR;
}
示例#7
0
static int gtkCanvasMapMethod(Ihandle* ih)
{
  GtkScrolledWindow* scrolled_window;
  void* visual;

  if (!ih->parent)
    return IUP_ERROR;

  ih->data->sb = iupBaseGetScrollbar(ih);

  visual = (void*)IupGetAttribute(ih, "VISUAL");   /* defined by the OpenGL Canvas in X11 or NULL */
  if (visual)
    iupgtkPushVisualAndColormap(visual, (void*)iupAttribGet(ih, "COLORMAP"));

  ih->handle = gtk_drawing_area_new();

  if (visual)
    gtk_widget_pop_colormap();

  if (!ih->handle)
      return IUP_ERROR;

#if GTK_CHECK_VERSION(2, 18, 0)
  /* CD will NOT work properly without this, must use always the CD-GDK driver */
  gtk_widget_set_has_window(ih->handle, TRUE);  
#endif

  scrolled_window = (GtkScrolledWindow*)gtk_scrolled_window_new(NULL, NULL);
  if (!scrolled_window)
    return IUP_ERROR;

  {
    /* to avoid the "cannot add non scrollable widget" warning */
#if GTK_CHECK_VERSION(2, 6, 0)
    GLogFunc def_func = g_log_set_default_handler(gtkCanvasDummyLogFunc, NULL);
#endif
    gtk_container_add((GtkContainer*)scrolled_window, ih->handle);
#if GTK_CHECK_VERSION(2, 6, 0)
    g_log_set_default_handler(def_func, NULL);
#endif
  }

  gtk_widget_show((GtkWidget*)scrolled_window);

  iupAttribSetStr(ih, "_IUP_EXTRAPARENT", (char*)scrolled_window);

  /* add to the parent, all GTK controls must call this. */
  iupgtkBaseAddToParent(ih);

  g_signal_connect(G_OBJECT(ih->handle), "focus-in-event",     G_CALLBACK(iupgtkFocusInOutEvent), ih);
  g_signal_connect(G_OBJECT(ih->handle), "focus-out-event",    G_CALLBACK(iupgtkFocusInOutEvent), ih);
  g_signal_connect(G_OBJECT(ih->handle), "key-press-event",    G_CALLBACK(iupgtkKeyPressEvent), ih);
  g_signal_connect(G_OBJECT(ih->handle), "key-release-event",  G_CALLBACK(iupgtkKeyReleaseEvent), ih);
  g_signal_connect(G_OBJECT(ih->handle), "enter-notify-event", G_CALLBACK(iupgtkEnterLeaveEvent), ih);
  g_signal_connect(G_OBJECT(ih->handle), "leave-notify-event", G_CALLBACK(iupgtkEnterLeaveEvent), ih);
  g_signal_connect(G_OBJECT(ih->handle), "show-help",          G_CALLBACK(iupgtkShowHelp), ih);

  g_signal_connect(G_OBJECT(ih->handle), "expose-event",       G_CALLBACK(gtkCanvasExposeEvent), ih);
  g_signal_connect(G_OBJECT(ih->handle), "button-press-event", G_CALLBACK(gtkCanvasButtonEvent), ih);
  g_signal_connect(G_OBJECT(ih->handle), "button-release-event",G_CALLBACK(gtkCanvasButtonEvent), ih);
  g_signal_connect(G_OBJECT(ih->handle), "motion-notify-event",G_CALLBACK(iupgtkMotionNotifyEvent), ih);
  g_signal_connect(G_OBJECT(ih->handle), "scroll-event",G_CALLBACK(gtkCanvasScrollEvent), ih);

#if GTK_CHECK_VERSION(2, 8, 0)
  g_signal_connect(G_OBJECT(gtk_scrolled_window_get_hscrollbar(scrolled_window)), "change-value",G_CALLBACK(gtkCanvasHChangeValue), ih);
  g_signal_connect(G_OBJECT(gtk_scrolled_window_get_vscrollbar(scrolled_window)), "change-value",G_CALLBACK(gtkCanvasVChangeValue), ih);
#endif

  /* To receive mouse events on a drawing area, you will need to enable them. */
  gtk_widget_add_events(ih->handle, GDK_EXPOSURE_MASK|
    GDK_POINTER_MOTION_MASK|GDK_POINTER_MOTION_HINT_MASK|
    GDK_BUTTON_PRESS_MASK|GDK_BUTTON_RELEASE_MASK|GDK_BUTTON_MOTION_MASK|
    GDK_KEY_PRESS_MASK|GDK_KEY_RELEASE_MASK|
    GDK_ENTER_NOTIFY_MASK|GDK_LEAVE_NOTIFY_MASK|
    GDK_FOCUS_CHANGE_MASK|GDK_STRUCTURE_MASK);

  /* To receive keyboard events, you will need to set the GTK_CAN_FOCUS flag on the drawing area. */
  if (ih->iclass->is_interactive)
  {
    if (iupAttribGetBoolean(ih, "CANFOCUS"))
      iupgtkSetCanFocus(ih->handle, 1);
  }

  if (iupAttribGetBoolean(ih, "BORDER"))
    gtk_scrolled_window_set_shadow_type(scrolled_window, GTK_SHADOW_IN); 
  else
    gtk_scrolled_window_set_shadow_type(scrolled_window, GTK_SHADOW_NONE);

  gtk_widget_realize((GtkWidget*)scrolled_window);
  gtk_widget_realize(ih->handle);

  /* must be connected after realize or a RESIZE_CB will happen before MAP_CB
    works only for the GtkDrawingArea. */
  g_signal_connect(G_OBJECT(ih->handle), "configure-event", G_CALLBACK(gtkCanvasConfigureEvent), ih);
  iupAttribSetStr(ih, "_IUP_GTK_FIRST_RESIZE", "1");

  /* configure for DRAG&DROP */
  if (IupGetCallback(ih, "DROPFILES_CB"))
    iupAttribSetStr(ih, "DRAGDROP", "YES");

  /* update a mnemonic in a label if necessary */
  iupgtkUpdateMnemonic(ih);

  /* configure scrollbar */
  if (ih->data->sb)
  {
    GtkPolicyType hscrollbar_policy = GTK_POLICY_NEVER, vscrollbar_policy = GTK_POLICY_NEVER;
    if (ih->data->sb & IUP_SB_HORIZ)
      hscrollbar_policy = GTK_POLICY_AUTOMATIC;
    if (ih->data->sb & IUP_SB_VERT)
      vscrollbar_policy = GTK_POLICY_AUTOMATIC;
    gtk_scrolled_window_set_policy(scrolled_window, hscrollbar_policy, vscrollbar_policy);
  }
  else
    gtk_scrolled_window_set_policy(scrolled_window, GTK_POLICY_NEVER, GTK_POLICY_NEVER);

  /* force the update of BGCOLOR here, to let derived classes ignore it if ACTION is defined */
  gtkCanvasSetBgColorAttrib(ih, iupAttribGetStr(ih, "BGCOLOR"));
    
  return IUP_NOERROR;
}