2
0

scribble_simple.pas 4.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170
  1. program scribble_simple;
  2. {$mode objfpc} {$H+}
  3. uses glib2, gtk2, gdk2;
  4. var
  5. pixmap : PGdkPixmap; (* Backing pixmap for drawing area *)
  6. (* Create a new backing pixmap of the appropriate size *)
  7. function configure_event ( widget : PGtkWidget;
  8. event : PGdkEventConfigure): gboolean; cdecl;
  9. begin
  10. if pixmap <> nil then
  11. g_object_unref (pixmap);
  12. pixmap := gdk_pixmap_new (widget^.window,
  13. widget^.allocation.width,
  14. widget^.allocation.height,
  15. -1);
  16. gdk_draw_rectangle (pixmap,
  17. widget^.style^.white_gc,
  18. gTRUE,
  19. 0, 0,
  20. widget^.allocation.width,
  21. widget^.allocation.height);
  22. configure_event := TRUE;
  23. end;
  24. (* Redraw the screen from the backing pixmap *)
  25. function expose_event ( widget : PGtkWidget;
  26. event : PGdkEventExpose) : gboolean; cdecl;
  27. begin
  28. gdk_draw_drawable (widget^.window,
  29. widget^.style^.fg_gc[GTK_WIDGET_STATE (widget)],
  30. pixmap,
  31. event^.area.x, event^.area.y,
  32. event^.area.x, event^.area.y,
  33. event^.area.width, event^.area.height);
  34. expose_event := FALSE;
  35. end;
  36. (* Draw a rectangle on the screen *)
  37. procedure draw_brush (widget : PGtkWidget;
  38. x, y : gdouble); cdecl;
  39. var
  40. update_rect : TGdkRectangle;
  41. begin
  42. update_rect.x := round (x - 5.0);
  43. update_rect.y := round (y - 5.0);
  44. update_rect.width := 10;
  45. update_rect.height := 10;
  46. gdk_draw_rectangle (pixmap,
  47. widget^.style^.black_gc,
  48. gTRUE,
  49. update_rect.x, update_rect.y,
  50. update_rect.width, update_rect.height);
  51. gtk_widget_queue_draw_area (widget,
  52. update_rect.x, update_rect.y,
  53. update_rect.width, update_rect.height);
  54. end;
  55. function button_press_event ( widget : PGtkWidget;
  56. event : PGdkEventbutton): gboolean; cdecl;
  57. begin
  58. if (event^.button = 1) and (pixmap <> NULL) then
  59. draw_brush (widget, event^.x, event^.y);
  60. button_press_event := TRUE;
  61. end;
  62. function motion_notify_event ( widget: PGtkWidget;
  63. event : PGdkEventMotion): gboolean; cdecl;
  64. var
  65. x, y : gint;
  66. state : TGdkModifierType;
  67. begin
  68. if event^.is_hint = gTRUE then
  69. gdk_window_get_pointer (event^.window, @x, @y, @state)
  70. else begin
  71. x := round (event^.x);
  72. y := round (event^.y);
  73. state := event^.state;
  74. end;
  75. if ((state and GDK_BUTTON1_MASK) <> 0) and (pixmap <> NULL) then
  76. draw_brush (widget, x, y);
  77. motion_notify_event := TRUE;
  78. end;
  79. procedure quit;
  80. begin
  81. halt;
  82. end;
  83. var
  84. window,
  85. drawing_area,
  86. vbox : PGtkWidget;
  87. button : PGtkWidget;
  88. begin
  89. gtk_init (@argc, @argv);
  90. window := gtk_window_new (GTK_WINDOW_TOPLEVEL);
  91. gtk_widget_set_name (window, 'Test Input');
  92. vbox := gtk_vbox_new (FALSE, 0);
  93. gtk_container_add (GTK_CONTAINER (window), vbox);
  94. gtk_widget_show (vbox);
  95. g_signal_connect (G_OBJECT (window), 'destroy',
  96. G_CALLBACK (@quit), NULL);
  97. (* Create the drawing area *)
  98. drawing_area := gtk_drawing_area_new ();
  99. gtk_widget_set_size_request (GTK_WIDGET (drawing_area), 200, 200);
  100. gtk_box_pack_start (GTK_BOX (vbox), drawing_area, TRUE, TRUE, 0);
  101. gtk_widget_show (drawing_area);
  102. (* Signals used to handle backing pixmap *)
  103. g_signal_connect (G_OBJECT (drawing_area), 'expose_event',
  104. G_CALLBACK (@expose_event), NULL);
  105. g_signal_connect (G_OBJECT (drawing_area),'configure_event',
  106. G_CALLBACK (@configure_event), NULL);
  107. (* Event signals *)
  108. g_signal_connect (G_OBJECT (drawing_area), 'motion_notify_event',
  109. G_CALLBACK (@motion_notify_event), NULL);
  110. g_signal_connect (G_OBJECT (drawing_area), 'button_press_event',
  111. G_CALLBACK (@button_press_event), NULL);
  112. gtk_widget_set_events (drawing_area, GDK_EXPOSURE_MASK
  113. or GDK_LEAVE_NOTIFY_MASK
  114. or GDK_BUTTON_PRESS_MASK
  115. or GDK_POINTER_MOTION_MASK
  116. or GDK_POINTER_MOTION_HINT_MASK);
  117. (* .. And a quit button *)
  118. button := gtk_button_new_with_label ('Quit');
  119. gtk_box_pack_start (GTK_BOX (vbox), button, FALSE, FALSE, 0);
  120. g_signal_connect_swapped (G_OBJECT (button), 'clicked',
  121. G_CALLBACK (@gtk_widget_destroy),
  122. window);
  123. gtk_widget_show (button);
  124. gtk_widget_show (window);
  125. gtk_main ();
  126. end.