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@')
37 elseif arg
[1] == '--help' or arg
[1] == '-h' then
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
47 elseif arg
[1] == '--show-extents' or arg
[1] == '-E' then
48 Adg
.switch_extents(true)
50 error('Invalid argument (' .. arg
[1] .. ')')
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
,
63 title
= 'Error from adg-demo',
71 -----------------------------------------------------------------
73 local piston
= Piston
.new
{
100 TITLE
= 'SAMPLE DRAWING',
103 DATE
= os
.date('%d/%m/%Y'),
107 -- GtkBuilder initialization
108 -----------------------------------------------------------------
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')
132 local function opener(button
, dialog
)
133 dialog
:set_transient_for(ui
.wndMain
)
135 button
.on_clicked
= function ()
137 Adg
.gtk_window_hide_here(dialog
)
143 -----------------------------------------------------------------
145 local canvas
= piston
.view
.detailed
146 canvas
:set_paper('iso_a4', Gtk
.PageOrientation
.LANDSCAPE
)
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
155 elseif event
.button
== 3 then
165 -----------------------------------------------------------------
167 opener(ui
.mainHelp
, ui
.wndHelp
)
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
)
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
197 return 'get_active', 'set_active', 'on_toggled'
198 elseif Gtk
.Entry
:is_type_of(widget
) then
200 return 'get_text', 'set_text', 'on_changed'
201 elseif Gtk
.SpinButton
:is_type_of(widget
) then
203 return 'get_value', 'set_value', 'on_changed'
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
]
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()
226 -- Unlock the UI on every widget change
227 local getter
, _
, notification
= entry_info(widget
)
228 widget
[notification
] = function ()
231 piston
.data
[field
] = widget
[getter
](widget
)
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
)
253 piston
.data
[field
] = widget
[getter
](widget
)
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
)
268 widget
[setter
](widget
, value
)
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)
291 for _
, radio
in pairs(ui
.saveAsPng
:get_group()) do
292 if radio
:get_active() then
293 suffix
= radio
:get_tooltip_markup()
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
311 -----------------------------------------------------------------
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
)
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()
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())
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()
360 -----------------------------------------------------------------
362 ui
.mainQuit
.on_clicked
= Gtk
.main_quit
366 -----------------------------------------------------------------
368 local window
= ui
.wndMain
369 window
.on_delete_event
= Gtk
.main_quit