doc: added adg-lua.tex for adg-demo.lua overview
[adg-lua.git] / adg-demo.lua.in
blob08bcfdb9271be4faf4bfc01584edac1f28adcfb7
1 --[[
3 This file is part of adg-lua.
4 Copyright (C) 2012-2013 Nicola Fontana <ntd at entidi.it>
6 adg-lua is free software; you can redistribute it and/or modify
7 it under the terms of the GNU Lesser General Public License as
8 published by the Free Software Foundation; either version 2 of
9 the License, or (at your option) any later version.
11 adg-lua is distributed in the hope that it will be useful, but
12 WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 GNU Lesser General Public License for more details.
16 You should have received a copy of the GNU Lesser General
17 Public License along with adg-lua; if not, write to the Free
18 Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
19 Boston, MA 02110-1301, USA.
24 local lgi = require 'lgi'
25 local GLib = lgi.require 'GLib'
26 local Gtk = lgi.require 'Gtk'
27 local Adg = lgi.require 'Adg'
28 local Piston = require 'piston'
31 -- Command line parsing
32 -----------------------------------------------------------------
34 if arg[1] == '--version' or arg[1] == '-V' then
35 print('adg-demo @VERSION@')
36 return 0
37 elseif arg[1] == '--help' or arg[1] == '-h' then
38 print([[
39 Usage:
40 ]] .. arg[0] .. [[ [OPTION...] - ADG demonstration program
42 -h, --help Show help options
43 -V, --version Display version information
44 -E, --show-extents Show the boundary boxes of every entity
45 ]])
46 return 0
47 elseif arg[1] == '--show-extents' or arg[1] == '-E' then
48 Adg.switch_extents(true)
49 elseif arg[1] then
50 error('Invalid argument (' .. arg[1] .. ')')
51 return 1
52 end
55 -- Customize error handler
56 -----------------------------------------------------------------
58 error = function (message)
59 local dialog = Gtk.MessageDialog {
60 message_type = Gtk.MessageType.ERROR,
61 buttons = Gtk.ButtonsType.CLOSE,
62 text = message,
63 title = 'Error from adg-demo',
65 dialog:run()
66 dialog:destroy()
67 end
70 -- Part definition
71 -----------------------------------------------------------------
73 local piston = Piston.new {
74 A = 55,
75 B = 20.6,
76 C = 2,
77 DHOLE = 2,
78 LHOLE = 3,
79 D1 = 9.3,
80 D2 = 6.5,
81 D3 = 13.8,
82 D4 = 6.5,
83 D5 = 4.5,
84 D6 = 7.2,
85 D7 = 2,
86 RD34 = 1,
87 RD56 = 0.2,
88 LD2 = 7,
89 LD3 = 3.5,
90 LD5 = 5,
91 LD6 = 1,
92 LD7 = 0.5,
93 GROOVE = false,
94 ZGROOVE = 16,
95 DGROOVE = 8.3,
96 LGROOVE = 1,
97 CHAMFER = 0.3,
99 -- Metadata
100 TITLE = 'SAMPLE DRAWING',
101 DRAWING = 'PISTON',
102 AUTHOR = 'adg-demo',
103 DATE = os.date('%d/%m/%Y'),
107 -- GtkBuilder initialization
108 -----------------------------------------------------------------
110 local ui
113 -- Path where the ADG library is installed: used for accessing
114 -- shared resources such as icons and GtkBuilder XML files.
115 local adg_data_dir = '@ADGDATADIR@'
117 -- This hack checks if ADGDATADIR has been expanded by
118 -- configure and provides a fallback otherwise. It allows to
119 -- directly run adg-demo.lua.in if ADG is installed in the
120 -- /usr prefix (as it happens to be on my system ;).
121 if adg_data_dir == '@ADGDATADIR' .. '@' then
122 adg_data_dir = '/usr/share/adg'
125 Adg.gtk_use_default_icons(adg_data_dir)
127 local builder = Gtk.Builder()
128 builder:add_from_file(adg_data_dir .. '/adg-demo.ui')
129 ui = builder.objects
132 local function opener(button, dialog)
133 dialog:set_transient_for(ui.wndMain)
135 button.on_clicked = function ()
136 dialog:run()
137 Adg.gtk_window_hide_here(dialog)
142 -- Canvas settings
143 -----------------------------------------------------------------
145 local canvas = piston.view.detailed
146 canvas:set_paper('iso_a4', Gtk.PageOrientation.LANDSCAPE)
147 canvas:autoscale()
149 local area = ui.mainCanvas
150 area:set_canvas(canvas)
151 area.on_button_press_event = function (area, event)
152 if event.button == 1 then
153 -- Restore the original zoom
154 area:reset()
155 elseif event.button == 3 then
156 canvas:autoscale()
157 area:queue_draw()
160 return false
164 -- Help dialog
165 -----------------------------------------------------------------
167 opener(ui.mainHelp, ui.wndHelp)
170 -- About dialog
171 -----------------------------------------------------------------
174 local dialog = ui.wndAbout
175 opener(ui.mainAbout, dialog)
177 -- The last icon is supposed to be the largest one:
178 -- check adg_gtk_use_default_icons() implementation.
179 local icon_list = Gtk.Window.get_default_icon_list()
180 local last_icon = icon_list[#icon_list]
181 dialog:set_logo(last_icon)
186 -- Edit dialog
187 -----------------------------------------------------------------
190 local dialog = ui.wndEdit
191 opener(ui.mainEdit, dialog)
192 dialog:set_position(Gtk.WindowPosition.MOUSE)
194 local function entry_info(widget)
195 if Gtk.ToggleButton:is_type_of(widget) then
196 -- Boolean value
197 return 'get_active', 'set_active', 'on_toggled'
198 elseif Gtk.Entry:is_type_of(widget) then
199 -- String value
200 return 'get_text', 'set_text', 'on_changed'
201 elseif Gtk.SpinButton:is_type_of(widget) then
202 -- Number value
203 return 'get_value', 'set_value', 'on_changed'
204 else
205 -- Unhandled type
206 return
210 local function lock_ui(status)
211 local sensitiveness = status == false
212 ui.btnApply:set_sensitive(sensitiveness)
213 ui.btnReset:set_sensitive(sensitiveness)
216 for field in pairs(piston.data) do
217 local widget = ui['edit' .. field]
218 if widget then
219 -- Synchronize GtkSpinButton to GtkAdjustment, that is
220 -- initialize the widget to its default value
221 if Gtk.SpinButton:is_type_of(widget) then
222 local adj = widget:get_adjustment()
223 adj:value_changed()
226 -- Unlock the UI on every widget change
227 local getter, _, notification = entry_info(widget)
228 widget[notification] = function ()
229 lock_ui(false)
231 piston.data[field] = widget[getter](widget)
235 piston:refresh()
237 ui.editGROOVE.on_toggled = function (self)
238 local toggled = self:get_active()
239 ui.editZGROOVE:set_sensitive(toggled)
240 ui.editZGROOVELabel:set_sensitive(toggled)
241 ui.editDGROOVE:set_sensitive(toggled)
242 ui.editDGROOVELabel:set_sensitive(toggled)
243 ui.editLGROOVE:set_sensitive(toggled)
244 ui.editLGROOVELabel:set_sensitive(toggled)
247 ui.btnApply.on_clicked = function ()
248 -- Refresh the piston data using the widgets
249 for field in pairs(piston.data) do
250 local widget = ui['edit' .. field]
251 local getter = entry_info(widget)
252 if getter then
253 piston.data[field] = widget[getter](widget)
257 piston:refresh()
258 area:queue_draw()
259 lock_ui()
262 ui.btnReset.on_clicked = function ()
263 -- Update the widgets using the piston data
264 for field, value in pairs(piston.data) do
265 local widget = ui['edit' .. field]
266 local _, setter = entry_info(widget)
267 if setter then
268 widget[setter](widget, value)
272 lock_ui()
278 -- Save as dialog
279 -----------------------------------------------------------------
282 local dialog = ui.wndSaveAs
283 opener(ui.mainSaveAs, dialog)
284 dialog:set_current_name('adg-demo')
286 dialog.on_response = function (dialog, response)
287 if response ~= Gtk.ResponseType.OK then return end
289 -- Retrieve the file suffix (format type)
290 local suffix = ''
291 for _, radio in pairs(ui.saveAsPng:get_group()) do
292 if radio:get_active() then
293 suffix = radio:get_tooltip_markup()
294 break
298 -- Forcibly append the proper suffix, if not yet present
299 local file = dialog:get_filename()
300 if not GLib.str_has_suffix(file, suffix) then
301 file = file .. suffix
303 _, err = canvas:export(file)
304 if err then error(err) end
310 -- Print dialog
311 -----------------------------------------------------------------
314 local settings
316 ui.mainPrint.on_clicked = function ()
317 local operation = Gtk.PrintOperation.new()
319 operation:set_use_full_page(operation, false)
320 operation:set_unit(Gtk.Unit.POINTS)
322 if settings then
323 operation:set_print_settings(settings)
326 if Gtk.PrintOperation.set_embed_page_setup then
327 operation:set_embed_page_setup(true)
330 local page_setup = canvas:get_page_setup()
331 if page_setup then
332 operation:set_default_page_setup(page_setup)
335 operation.on_begin_print = function ()
336 operation:set_n_pages(1)
339 operation.on_draw_page = function (operation, context)
340 local cr = context:get_cairo_context()
342 local old_map = canvas:get_global_map()
343 canvas:set_global_map(Adg.matrix_identity())
344 canvas:render(cr)
345 canvas:set_global_map(old_map)
348 local result, err = operation:run(Gtk.PrintOperationAction.PRINT_DIALOG, ui.wndMain)
349 if result == Gtk.PrintOperationResult.APPLY then
350 settings = operation:get_print_settings()
351 elseif err then
352 error(err)
359 -- Quit command
360 -----------------------------------------------------------------
362 ui.mainQuit.on_clicked = Gtk.main_quit
365 -- Main
366 -----------------------------------------------------------------
368 local window = ui.wndMain
369 window.on_delete_event = Gtk.main_quit
370 window:show_all()
372 Gtk.main()