demo-drawingarea.lua 4.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159
  1. return function(parent, dir)
  2. local lgi = require 'lgi'
  3. local Gtk = lgi.Gtk
  4. local Gdk = lgi.Gdk
  5. local cairo = lgi.cairo
  6. local window = Gtk.Window {
  7. title = "Drawing Area",
  8. border_width = 8,
  9. Gtk.Box {
  10. orientation = 'VERTICAL',
  11. spacing = 8,
  12. border_width = 8,
  13. Gtk.Label {
  14. use_markup = true,
  15. label = "<u>Checkerboard pattern</u>",
  16. },
  17. Gtk.Frame {
  18. shadow_type = 'IN',
  19. expand = true,
  20. Gtk.DrawingArea {
  21. id = 'checkerboard',
  22. width = 100,
  23. height = 100,
  24. },
  25. },
  26. Gtk.Label {
  27. use_markup = true,
  28. label = "<u>Scribble area</u>",
  29. },
  30. Gtk.Frame {
  31. shadow_type = 'IN',
  32. expand = true,
  33. Gtk.DrawingArea {
  34. id = 'scribble',
  35. width = 100,
  36. height = 100,
  37. },
  38. },
  39. },
  40. }
  41. -- Handling of checkerboard area.
  42. local SPACING = 2
  43. local CHECK_SIZE = 10
  44. function window.child.checkerboard:on_draw(cr)
  45. local i = SPACING
  46. local xcount = 0
  47. while i < self.width do
  48. local j = SPACING
  49. local ycount = xcount % 2
  50. while j < self.height do
  51. if ycount % 2 ~= 0 then
  52. cr:set_source_rgb(0.45777, 0, 0.45777)
  53. else
  54. cr:set_source_rgb(1, 1, 1)
  55. end
  56. cr:rectangle(i, j, CHECK_SIZE, CHECK_SIZE)
  57. cr:fill()
  58. j = j + CHECK_SIZE + SPACING
  59. ycount = ycount + 1
  60. end
  61. i = i + CHECK_SIZE + SPACING
  62. xcount = xcount + 1
  63. end
  64. return true
  65. end
  66. -- Setup and handling of scribble area.
  67. local scribble = window.child.scribble
  68. local surface
  69. function scribble:on_configure_event(event)
  70. -- Create new surface of appropriate size to store the scribbles.
  71. local allocation = self.allocation
  72. surface = self.window:create_similar_surface(
  73. 'COLOR', allocation.width, allocation.height)
  74. -- Initialize the surface to white.
  75. local cr = cairo.Context.create(surface)
  76. cr:set_source_rgb(1, 1, 1)
  77. cr:paint()
  78. return true
  79. end
  80. function scribble:on_draw(cr)
  81. -- Redraw the screen from the buffer.
  82. cr:set_source_surface(surface, 0, 0)
  83. cr:paint()
  84. return true
  85. end
  86. -- Draw a rectangle on the scribble surface.
  87. local function draw_brush(widget, x, y)
  88. local update_rect = Gdk.Rectangle { x = x - 3, y = y - 3,
  89. width = 6, height = 6 }
  90. -- Paint to the scribble surface
  91. local cr = cairo.Context(surface)
  92. cr:rectangle(update_rect)
  93. cr:fill()
  94. -- Invalidate affected region of the paint area.
  95. widget.window:invalidate_rect(update_rect, false)
  96. end
  97. function scribble:on_motion_notify_event(event)
  98. -- This call is very important; it requests the next motion event.
  99. -- If you don't call Gdk.Window.get_pointer() you'll only get
  100. -- a single motion event. The reason is that we specified
  101. -- Gdk.EventMask.POINTER_MOTION_HINT_MASK to Gtk.Widget.add_events().
  102. -- If we hadn't specified that, we could just use event.x, event.y
  103. -- as the pointer location. But we'd also get deluged in events.
  104. -- By requesting the next event as we handle the current one,
  105. -- we avoid getting a huge number of events faster than we
  106. -- can cope.
  107. local _, x, y, state = event.window:get_device_position(event.device)
  108. if state.BUTTON1_MASK then
  109. draw_brush(self, x, y)
  110. end
  111. return true
  112. end
  113. function scribble:on_button_press_event(event)
  114. if event.button == Gdk.BUTTON_PRIMARY then
  115. draw_brush(self, event.x, event.y)
  116. end
  117. return true
  118. end
  119. scribble:add_events(Gdk.EventMask {
  120. 'LEAVE_NOTIFY_MASK',
  121. 'BUTTON_PRESS_MASK',
  122. 'POINTER_MOTION_MASK',
  123. 'POINTER_MOTION_HINT_MASK' })
  124. window:show_all()
  125. return window
  126. end,
  127. "Drawing Area",
  128. table.concat {
  129. [[Gtk.DrawingArea is a blank area where you can draw custom displays ]],
  130. [[of various kinds.
  131. ]],
  132. [[This demo has two drawing areas. The checkerboard area shows how ]],
  133. [[you can just draw something; all you have to do is write a signal ]],
  134. [[handler for expose_event, as shown here.
  135. ]],
  136. [[The "scribble" area is a bit more advanced, and shows how to handle ]],
  137. [[events such as button presses and mouse motion. Click the mouse ]],
  138. [[and drag in the scribble area to draw squiggles. Resize the window ]],
  139. [[to clear the area.]]
  140. }